Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 289 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer | 25591511 | 6 hrs ago | IN | 0 HYPE | 0.00001323 | ||||
| Send | 25081164 | 6 days ago | IN | 0.00392481 HYPE | 0.00013199 | ||||
| Transfer | 25081096 | 6 days ago | IN | 0 HYPE | 0 | ||||
| Send | 25080911 | 6 days ago | IN | 0.00392481 HYPE | 0.00114108 | ||||
| Transfer | 25080888 | 6 days ago | IN | 0 HYPE | 0 | ||||
| Transfer | 25080104 | 6 days ago | IN | 0 HYPE | 0.00016052 | ||||
| Transfer | 25073156 | 6 days ago | IN | 0 HYPE | 0.00002605 | ||||
| Transfer | 25063333 | 6 days ago | IN | 0 HYPE | 0.0000117 | ||||
| Transfer | 24990291 | 7 days ago | IN | 0 HYPE | 0.00003437 | ||||
| Transfer | 24988784 | 7 days ago | IN | 0 HYPE | 0.00008892 | ||||
| Transfer | 24987978 | 7 days ago | IN | 0 HYPE | 0.00000412 | ||||
| Transfer | 24987835 | 7 days ago | IN | 0 HYPE | 0.00003437 | ||||
| Transfer | 24987137 | 7 days ago | IN | 0 HYPE | 0.0000378 | ||||
| Transfer | 24980785 | 7 days ago | IN | 0 HYPE | 0.00000498 | ||||
| Transfer | 24980257 | 7 days ago | IN | 0 HYPE | 0.00013748 | ||||
| Transfer | 24725520 | 10 days ago | IN | 0 HYPE | 0.00015384 | ||||
| Transfer | 24724870 | 10 days ago | IN | 0 HYPE | 0.00004577 | ||||
| Transfer | 24723495 | 10 days ago | IN | 0 HYPE | 0.0000489 | ||||
| Transfer | 24722970 | 10 days ago | IN | 0 HYPE | 0.00005815 | ||||
| Transfer | 24628152 | 11 days ago | IN | 0 HYPE | 0.00002012 | ||||
| Send | 24540805 | 12 days ago | IN | 0.03561414 HYPE | 0.0006417 | ||||
| Send | 24540708 | 12 days ago | IN | 0.00352279 HYPE | 0.00060708 | ||||
| Transfer | 24539496 | 12 days ago | IN | 0 HYPE | 0.00001144 | ||||
| Transfer | 24538840 | 12 days ago | IN | 0 HYPE | 0.00002701 | ||||
| Transfer | 24538345 | 12 days ago | IN | 0 HYPE | 0.00001298 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 25081164 | 6 days ago | 0.00392481 HYPE | ||||
| 25080911 | 6 days ago | 0.00392481 HYPE | ||||
| 24540805 | 12 days ago | 0.03561414 HYPE | ||||
| 24540708 | 12 days ago | 0.00352279 HYPE | ||||
| 24509185 | 12 days ago | 0.00352279 HYPE | ||||
| 20775354 | 55 days ago | 0.00245784 HYPE | ||||
| 20775157 | 55 days ago | 0.00245784 HYPE | ||||
| 20774941 | 55 days ago | 0.00245784 HYPE | ||||
| 20774763 | 55 days ago | 0.00245784 HYPE | ||||
| 20774444 | 55 days ago | 0.00245784 HYPE | ||||
| 19551202 | 69 days ago | 0.07399672 HYPE | ||||
| 19551135 | 69 days ago | 0.02399672 HYPE | ||||
| 19541129 | 69 days ago | 0.01847046 HYPE | ||||
| 19536564 | 69 days ago | 0.02089253 HYPE | ||||
| 19535555 | 69 days ago | 0.0253105 HYPE | ||||
| 19535209 | 69 days ago | 0.02061217 HYPE | ||||
| 19535111 | 69 days ago | 0.02399672 HYPE | ||||
| 19535005 | 69 days ago | 0.01779611 HYPE | ||||
| 19534963 | 69 days ago | 0.01779611 HYPE | ||||
| 19534944 | 69 days ago | 0.01779611 HYPE | ||||
| 19533878 | 69 days ago | 0.01876818 HYPE | ||||
| 19533824 | 69 days ago | 0.01876818 HYPE | ||||
| 19532460 | 69 days ago | 0.02256942 HYPE | ||||
| 19532426 | 69 days ago | 0.02256942 HYPE | ||||
| 19532313 | 69 days ago | 0.02372721 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RektOFT
Compiler Version
v0.8.30+commit.73712a01
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol";
contract RektOFT is OFT {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate
) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {}
/**
* @dev Retrieves the shared decimals of the OFT.
* @return The shared decimals of the OFT.
*
* @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap
* Lowest common decimal denominator between chains.
* Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).
* Our token exceeds this totalSupply(420,690,000,000,000 ethers), we override the sharedDecimals function with something smaller.
* 4 sharedDecimals will be 1,844,674,407,370,955.1615
*/
function sharedDecimals() public pure override returns (uint8) {
return 4;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IMessageLibManager } from "./IMessageLibManager.sol";
import { IMessagingComposer } from "./IMessagingComposer.sol";
import { IMessagingChannel } from "./IMessagingChannel.sol";
import { IMessagingContext } from "./IMessagingContext.sol";
struct MessagingParams {
uint32 dstEid;
bytes32 receiver;
bytes message;
bytes options;
bool payInLzToken;
}
struct MessagingReceipt {
bytes32 guid;
uint64 nonce;
MessagingFee fee;
}
struct MessagingFee {
uint256 nativeFee;
uint256 lzTokenFee;
}
struct Origin {
uint32 srcEid;
bytes32 sender;
uint64 nonce;
}
interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {
event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);
event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);
event PacketDelivered(Origin origin, address receiver);
event LzReceiveAlert(
address indexed receiver,
address indexed executor,
Origin origin,
bytes32 guid,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
event LzTokenSet(address token);
event DelegateSet(address sender, address delegate);
function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);
function send(
MessagingParams calldata _params,
address _refundAddress
) external payable returns (MessagingReceipt memory);
function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;
function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);
function initializable(Origin calldata _origin, address _receiver) external view returns (bool);
function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;
// oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;
function setLzToken(address _lzToken) external;
function lzToken() external view returns (address);
function nativeToken() external view returns (address);
function setDelegate(address _delegate) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { Origin } from "./ILayerZeroEndpointV2.sol";
interface ILayerZeroReceiver {
function allowInitializePath(Origin calldata _origin) external view returns (bool);
function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { SetConfigParam } from "./IMessageLibManager.sol";
enum MessageLibType {
Send,
Receive,
SendAndReceive
}
interface IMessageLib is IERC165 {
function setConfig(address _oapp, SetConfigParam[] calldata _config) external;
function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);
function isSupportedEid(uint32 _eid) external view returns (bool);
// message libs of same major version are compatible
function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);
function messageLibType() external view returns (MessageLibType);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
struct SetConfigParam {
uint32 eid;
uint32 configType;
bytes config;
}
interface IMessageLibManager {
struct Timeout {
address lib;
uint256 expiry;
}
event LibraryRegistered(address newLib);
event DefaultSendLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibrarySet(uint32 eid, address newLib);
event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);
event SendLibrarySet(address sender, uint32 eid, address newLib);
event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);
event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);
function registerLibrary(address _lib) external;
function isRegisteredLibrary(address _lib) external view returns (bool);
function getRegisteredLibraries() external view returns (address[] memory);
function setDefaultSendLibrary(uint32 _eid, address _newLib) external;
function defaultSendLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function defaultReceiveLibrary(uint32 _eid) external view returns (address);
function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;
function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);
function isSupportedEid(uint32 _eid) external view returns (bool);
function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);
/// ------------------- OApp interfaces -------------------
function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;
function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);
function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);
function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;
function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);
function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;
function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);
function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;
function getConfig(
address _oapp,
address _lib,
uint32 _eid,
uint32 _configType
) external view returns (bytes memory config);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingChannel {
event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);
event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);
function eid() external view returns (uint32);
// this is an emergency function if a message cannot be verified for some reasons
// required to provide _nextNonce to avoid race condition
function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;
function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;
function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);
function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);
function inboundPayloadHash(
address _receiver,
uint32 _srcEid,
bytes32 _sender,
uint64 _nonce
) external view returns (bytes32);
function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingComposer {
event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);
event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);
event LzComposeAlert(
address indexed from,
address indexed to,
address indexed executor,
bytes32 guid,
uint16 index,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);
function composeQueue(
address _from,
address _to,
bytes32 _guid,
uint16 _index
) external view returns (bytes32 messageHash);
function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;
function lzCompose(
address _from,
address _to,
bytes32 _guid,
uint16 _index,
bytes calldata _message,
bytes calldata _extraData
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IMessagingContext {
function isSendingMessage() external view returns (bool);
function getSendContext() external view returns (uint32 dstEid, address sender);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import { MessagingFee } from "./ILayerZeroEndpointV2.sol";
import { IMessageLib } from "./IMessageLib.sol";
struct Packet {
uint64 nonce;
uint32 srcEid;
address sender;
uint32 dstEid;
bytes32 receiver;
bytes32 guid;
bytes message;
}
interface ISendLib is IMessageLib {
function send(
Packet calldata _packet,
bytes calldata _options,
bool _payInLzToken
) external returns (MessagingFee memory, bytes memory encodedPacket);
function quote(
Packet calldata _packet,
bytes calldata _options,
bool _payInLzToken
) external view returns (MessagingFee memory);
function setTreasury(address _treasury) external;
function withdrawFee(address _to, uint256 _amount) external;
function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;
}// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
library AddressCast {
error AddressCast_InvalidSizeForAddress();
error AddressCast_InvalidAddress();
function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {
if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();
result = bytes32(_addressBytes);
unchecked {
uint256 offset = 32 - _addressBytes.length;
result = result >> (offset * 8);
}
}
function toBytes32(address _address) internal pure returns (bytes32 result) {
result = bytes32(uint256(uint160(_address)));
}
function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {
if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();
result = new bytes(_size);
unchecked {
uint256 offset = 256 - _size * 8;
assembly {
mstore(add(result, 32), shl(offset, _addressBytes32))
}
}
}
function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {
result = address(uint160(uint256(_addressBytes32)));
}
function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {
if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();
result = address(bytes20(_addressBytes));
}
}// SPDX-License-Identifier: LZBL-1.2
pragma solidity ^0.8.20;
import { Packet } from "../../interfaces/ISendLib.sol";
import { AddressCast } from "../../libs/AddressCast.sol";
library PacketV1Codec {
using AddressCast for address;
using AddressCast for bytes32;
uint8 internal constant PACKET_VERSION = 1;
// header (version + nonce + path)
// version
uint256 private constant PACKET_VERSION_OFFSET = 0;
// nonce
uint256 private constant NONCE_OFFSET = 1;
// path
uint256 private constant SRC_EID_OFFSET = 9;
uint256 private constant SENDER_OFFSET = 13;
uint256 private constant DST_EID_OFFSET = 45;
uint256 private constant RECEIVER_OFFSET = 49;
// payload (guid + message)
uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)
uint256 private constant MESSAGE_OFFSET = 113;
function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {
encodedPacket = abi.encodePacked(
PACKET_VERSION,
_packet.nonce,
_packet.srcEid,
_packet.sender.toBytes32(),
_packet.dstEid,
_packet.receiver,
_packet.guid,
_packet.message
);
}
function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {
return
abi.encodePacked(
PACKET_VERSION,
_packet.nonce,
_packet.srcEid,
_packet.sender.toBytes32(),
_packet.dstEid,
_packet.receiver
);
}
function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {
return abi.encodePacked(_packet.guid, _packet.message);
}
function header(bytes calldata _packet) internal pure returns (bytes calldata) {
return _packet[0:GUID_OFFSET];
}
function version(bytes calldata _packet) internal pure returns (uint8) {
return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));
}
function nonce(bytes calldata _packet) internal pure returns (uint64) {
return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));
}
function srcEid(bytes calldata _packet) internal pure returns (uint32) {
return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));
}
function sender(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);
}
function senderAddressB20(bytes calldata _packet) internal pure returns (address) {
return sender(_packet).toAddress();
}
function dstEid(bytes calldata _packet) internal pure returns (uint32) {
return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));
}
function receiver(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);
}
function receiverB20(bytes calldata _packet) internal pure returns (address) {
return receiver(_packet).toAddress();
}
function guid(bytes calldata _packet) internal pure returns (bytes32) {
return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);
}
function message(bytes calldata _packet) internal pure returns (bytes calldata) {
return bytes(_packet[MESSAGE_OFFSET:]);
}
function payload(bytes calldata _packet) internal pure returns (bytes calldata) {
return bytes(_packet[GUID_OFFSET:]);
}
function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {
return keccak256(payload(_packet));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
/**
* @title IOAppCore
*/
interface IOAppCore {
// Custom error messages
error OnlyPeer(uint32 eid, bytes32 sender);
error NoPeer(uint32 eid);
error InvalidEndpointCall();
error InvalidDelegate();
// Event emitted when a peer (OApp) is set for a corresponding endpoint
event PeerSet(uint32 eid, bytes32 peer);
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*/
function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);
/**
* @notice Retrieves the LayerZero endpoint associated with the OApp.
* @return iEndpoint The LayerZero endpoint as an interface.
*/
function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);
/**
* @notice Retrieves the peer (OApp) associated with a corresponding endpoint.
* @param _eid The endpoint ID.
* @return peer The peer address (OApp instance) associated with the corresponding endpoint.
*/
function peers(uint32 _eid) external view returns (bytes32 peer);
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*/
function setPeer(uint32 _eid, bytes32 _peer) external;
/**
* @notice Sets the delegate address for the OApp Core.
* @param _delegate The address of the delegate to be set.
*/
function setDelegate(address _delegate) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title IOAppMsgInspector
* @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.
*/
interface IOAppMsgInspector {
// Custom error message for inspection failure
error InspectionFailed(bytes message, bytes options);
/**
* @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.
* @param _message The message payload to be inspected.
* @param _options Additional options or parameters for inspection.
* @return valid A boolean indicating whether the inspection passed (true) or failed (false).
*
* @dev Optionally done as a revert, OR use the boolean provided to handle the failure.
*/
function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @dev Struct representing enforced option parameters.
*/
struct EnforcedOptionParam {
uint32 eid; // Endpoint ID
uint16 msgType; // Message Type
bytes options; // Additional options
}
/**
* @title IOAppOptionsType3
* @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.
*/
interface IOAppOptionsType3 {
// Custom error message for invalid options
error InvalidOptions(bytes options);
// Event emitted when enforced options are set
event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);
/**
* @notice Sets enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*/
function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;
/**
* @notice Combines options for a given endpoint and message type.
* @param _eid The endpoint ID.
* @param _msgType The OApp message type.
* @param _extraOptions Additional options passed by the caller.
* @return options The combination of caller specified options AND enforced options.
*/
function combineOptions(
uint32 _eid,
uint16 _msgType,
bytes calldata _extraOptions
) external view returns (bytes memory options);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol";
interface IOAppReceiver is ILayerZeroReceiver {
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata _origin,
bytes calldata _message,
address _sender
) external view returns (bool isSender);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppOptionsType3, EnforcedOptionParam } from "../interfaces/IOAppOptionsType3.sol";
/**
* @title OAppOptionsType3
* @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.
*/
abstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {
uint16 internal constant OPTION_TYPE_3 = 3;
// @dev The "msgType" should be defined in the child contract.
mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;
/**
* @dev Sets the enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
* @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
* eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
* if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
*/
function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {
_setEnforcedOptions(_enforcedOptions);
}
/**
* @dev Sets the enforced options for specific endpoint and message type combinations.
* @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.
*
* @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.
* @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.
* eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay
* if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().
*/
function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {
for (uint256 i = 0; i < _enforcedOptions.length; i++) {
// @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.
_assertOptionsType3(_enforcedOptions[i].options);
enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;
}
emit EnforcedOptionSet(_enforcedOptions);
}
/**
* @notice Combines options for a given endpoint and message type.
* @param _eid The endpoint ID.
* @param _msgType The OAPP message type.
* @param _extraOptions Additional options passed by the caller.
* @return options The combination of caller specified options AND enforced options.
*
* @dev If there is an enforced lzReceive option:
* - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}
* - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.
* @dev This presence of duplicated options is handled off-chain in the verifier/executor.
*/
function combineOptions(
uint32 _eid,
uint16 _msgType,
bytes calldata _extraOptions
) public view virtual returns (bytes memory) {
bytes memory enforced = enforcedOptions[_eid][_msgType];
// No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.
if (enforced.length == 0) return _extraOptions;
// No caller options, return enforced
if (_extraOptions.length == 0) return enforced;
// @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.
if (_extraOptions.length >= 2) {
_assertOptionsType3(_extraOptions);
// @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.
return bytes.concat(enforced, _extraOptions[2:]);
}
// No valid set of options was found.
revert InvalidOptions(_extraOptions);
}
/**
* @dev Internal function to assert that options are of type 3.
* @param _options The options to be checked.
*/
function _assertOptionsType3(bytes memory _options) internal pure virtual {
uint16 optionsType;
assembly {
optionsType := mload(add(_options, 2))
}
if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol";
// @dev Import the 'Origin' so it's exposed to OApp implementers
// solhint-disable-next-line no-unused-import
import { OAppReceiver, Origin } from "./OAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OApp
* @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.
*/
abstract contract OApp is OAppSender, OAppReceiver {
/**
* @dev Constructor to initialize the OApp with the provided endpoint and owner.
* @param _endpoint The address of the LOCAL LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol implementation.
* @return receiverVersion The version of the OAppReceiver.sol implementation.
*/
function oAppVersion()
public
pure
virtual
override(OAppSender, OAppReceiver)
returns (uint64 senderVersion, uint64 receiverVersion)
{
return (SENDER_VERSION, RECEIVER_VERSION);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IOAppCore, ILayerZeroEndpointV2 } from "./interfaces/IOAppCore.sol";
/**
* @title OAppCore
* @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.
*/
abstract contract OAppCore is IOAppCore, Ownable {
// The LayerZero endpoint associated with the given OApp
ILayerZeroEndpointV2 public immutable endpoint;
// Mapping to store peers associated with corresponding endpoints
mapping(uint32 eid => bytes32 peer) public peers;
/**
* @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.
* @param _endpoint The address of the LOCAL Layer Zero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*
* @dev The delegate typically should be set as the owner of the contract.
*/
constructor(address _endpoint, address _delegate) {
endpoint = ILayerZeroEndpointV2(_endpoint);
if (_delegate == address(0)) revert InvalidDelegate();
endpoint.setDelegate(_delegate);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {
_setPeer(_eid, _peer);
}
/**
* @notice Sets the peer address (OApp instance) for a corresponding endpoint.
* @param _eid The endpoint ID.
* @param _peer The address of the peer to be associated with the corresponding endpoint.
*
* @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.
* @dev Set this to bytes32(0) to remove the peer address.
* @dev Peer is a bytes32 to accommodate non-evm chains.
*/
function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {
peers[_eid] = _peer;
emit PeerSet(_eid, _peer);
}
/**
* @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.
* ie. the peer is set to bytes32(0).
* @param _eid The endpoint ID.
* @return peer The address of the peer associated with the specified endpoint.
*/
function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {
bytes32 peer = peers[_eid];
if (peer == bytes32(0)) revert NoPeer(_eid);
return peer;
}
/**
* @notice Sets the delegate address for the OApp.
* @param _delegate The address of the delegate to be set.
*
* @dev Only the owner/admin of the OApp can call this function.
* @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.
*/
function setDelegate(address _delegate) public onlyOwner {
endpoint.setDelegate(_delegate);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppReceiver
* @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.
*/
abstract contract OAppReceiver is IOAppReceiver, OAppCore {
// Custom error message for when the caller is not the registered endpoint/
error OnlyEndpoint(address addr);
// @dev The version of the OAppReceiver implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant RECEIVER_VERSION = 2;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.
* ie. this is a RECEIVE only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (0, RECEIVER_VERSION);
}
/**
* @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.
* @dev _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @dev _message The lzReceive payload.
* @param _sender The sender address.
* @return isSender Is a valid sender.
*
* @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.
* @dev The default sender IS the OAppReceiver implementer.
*/
function isComposeMsgSender(
Origin calldata /*_origin*/,
bytes calldata /*_message*/,
address _sender
) public view virtual returns (bool) {
return _sender == address(this);
}
/**
* @notice Checks if the path initialization is allowed based on the provided origin.
* @param origin The origin information containing the source endpoint and sender address.
* @return Whether the path has been initialized.
*
* @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.
* @dev This defaults to assuming if a peer has been set, its initialized.
* Can be overridden by the OApp if there is other logic to determine this.
*/
function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {
return peers[origin.srcEid] == origin.sender;
}
/**
* @notice Retrieves the next nonce for a given source endpoint and sender address.
* @dev _srcEid The source endpoint ID.
* @dev _sender The sender address.
* @return nonce The next nonce.
*
* @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.
* @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.
* @dev This is also enforced by the OApp.
* @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.
*/
function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {
return 0;
}
/**
* @dev Entry point for receiving messages or packets from the endpoint.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The payload of the received message.
* @param _executor The address of the executor for the received message.
* @param _extraData Additional arbitrary data provided by the corresponding executor.
*
* @dev Entry point for receiving msg/packet from the LayerZero endpoint.
*/
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) public payable virtual {
// Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.
if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);
// Ensure that the sender matches the expected peer for the source endpoint.
if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);
// Call the internal OApp implementation of lzReceive.
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "./OAppCore.sol";
/**
* @title OAppSender
* @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.
*/
abstract contract OAppSender is OAppCore {
using SafeERC20 for IERC20;
// Custom error messages
error NotEnoughNative(uint256 msgValue);
error LzTokenUnavailable();
// @dev The version of the OAppSender implementation.
// @dev Version is bumped when changes are made to this contract.
uint64 internal constant SENDER_VERSION = 1;
/**
* @notice Retrieves the OApp version information.
* @return senderVersion The version of the OAppSender.sol contract.
* @return receiverVersion The version of the OAppReceiver.sol contract.
*
* @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.
* ie. this is a SEND only OApp.
* @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions
*/
function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {
return (SENDER_VERSION, 0);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.
* @return fee The calculated MessagingFee for the message.
* - nativeFee: The native fee for the message.
* - lzTokenFee: The LZ token fee for the message.
*/
function _quote(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
bool _payInLzToken
) internal view virtual returns (MessagingFee memory fee) {
return
endpoint.quote(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),
address(this)
);
}
/**
* @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.
* @param _dstEid The destination endpoint ID.
* @param _message The message payload.
* @param _options Additional options for the message.
* @param _fee The calculated LayerZero fee for the message.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess fee values sent to the endpoint.
* @return receipt The receipt for the sent message.
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function _lzSend(
uint32 _dstEid,
bytes memory _message,
bytes memory _options,
MessagingFee memory _fee,
address _refundAddress
) internal virtual returns (MessagingReceipt memory receipt) {
// @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.
uint256 messageValue = _payNative(_fee.nativeFee);
if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);
return
// solhint-disable-next-line check-send-result
endpoint.send{ value: messageValue }(
MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),
_refundAddress
);
}
/**
* @dev Internal function to pay the native fee associated with the message.
* @param _nativeFee The native fee to be paid.
* @return nativeFee The amount of native currency paid.
*
* @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,
* this will need to be overridden because msg.value would contain multiple lzFees.
* @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.
* @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.
* @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.
*/
function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {
if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);
return _nativeFee;
}
/**
* @dev Internal function to pay the LZ token fee associated with the message.
* @param _lzTokenFee The LZ token fee to be paid.
*
* @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.
* @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().
*/
function _payLzToken(uint256 _lzTokenFee) internal virtual {
// @dev Cannot cache the token because it is not immutable in the endpoint.
address lzToken = endpoint.lzToken();
if (lzToken == address(0)) revert LzTokenUnavailable();
// Pay LZ token fee by sending tokens to the endpoint.
IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
// solhint-disable-next-line no-unused-import
import { InboundPacket, Origin } from "../libs/Packet.sol";
/**
* @title IOAppPreCrimeSimulator Interface
* @dev Interface for the preCrime simulation functionality in an OApp.
*/
interface IOAppPreCrimeSimulator {
// @dev simulation result used in PreCrime implementation
error SimulationResult(bytes result);
error OnlySelf();
/**
* @dev Emitted when the preCrime contract address is set.
* @param preCrimeAddress The address of the preCrime contract.
*/
event PreCrimeSet(address preCrimeAddress);
/**
* @dev Retrieves the address of the preCrime contract implementation.
* @return The address of the preCrime contract.
*/
function preCrime() external view returns (address);
/**
* @dev Retrieves the address of the OApp contract.
* @return The address of the OApp contract.
*/
function oApp() external view returns (address);
/**
* @dev Sets the preCrime contract address.
* @param _preCrime The address of the preCrime contract.
*/
function setPreCrime(address _preCrime) external;
/**
* @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.
* @param _packets An array of LayerZero InboundPacket objects representing received packets.
*/
function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;
/**
* @dev checks if the specified peer is considered 'trusted' by the OApp.
* @param _eid The endpoint Id to check.
* @param _peer The peer to check.
* @return Whether the peer passed is considered 'trusted' by the OApp.
*/
function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
struct PreCrimePeer {
uint32 eid;
bytes32 preCrime;
bytes32 oApp;
}
// TODO not done yet
interface IPreCrime {
error OnlyOffChain();
// for simulate()
error PacketOversize(uint256 max, uint256 actual);
error PacketUnsorted();
error SimulationFailed(bytes reason);
// for preCrime()
error SimulationResultNotFound(uint32 eid);
error InvalidSimulationResult(uint32 eid, bytes reason);
error CrimeFound(bytes crime);
function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);
function simulate(
bytes[] calldata _packets,
uint256[] calldata _packetMsgValues
) external payable returns (bytes memory);
function buildSimulationResult() external view returns (bytes memory);
function preCrime(
bytes[] calldata _packets,
uint256[] calldata _packetMsgValues,
bytes[] calldata _simulations
) external;
function version() external view returns (uint64 major, uint8 minor);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
import { PacketV1Codec } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol";
/**
* @title InboundPacket
* @dev Structure representing an inbound packet received by the contract.
*/
struct InboundPacket {
Origin origin; // Origin information of the packet.
uint32 dstEid; // Destination endpointId of the packet.
address receiver; // Receiver address for the packet.
bytes32 guid; // Unique identifier of the packet.
uint256 value; // msg.value of the packet.
address executor; // Executor address for the packet.
bytes message; // Message payload of the packet.
bytes extraData; // Additional arbitrary data for the packet.
}
/**
* @title PacketDecoder
* @dev Library for decoding LayerZero packets.
*/
library PacketDecoder {
using PacketV1Codec for bytes;
/**
* @dev Decode an inbound packet from the given packet data.
* @param _packet The packet data to decode.
* @return packet An InboundPacket struct representing the decoded packet.
*/
function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {
packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());
packet.dstEid = _packet.dstEid();
packet.receiver = _packet.receiverB20();
packet.guid = _packet.guid();
packet.message = _packet.message();
}
/**
* @dev Decode multiple inbound packets from the given packet data and associated message values.
* @param _packets An array of packet data to decode.
* @param _packetMsgValues An array of associated message values for each packet.
* @return packets An array of InboundPacket structs representing the decoded packets.
*/
function decode(
bytes[] calldata _packets,
uint256[] memory _packetMsgValues
) internal pure returns (InboundPacket[] memory packets) {
packets = new InboundPacket[](_packets.length);
for (uint256 i = 0; i < _packets.length; i++) {
bytes calldata packet = _packets[i];
packets[i] = PacketDecoder.decode(packet);
// @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.
packets[i].value = _packetMsgValues[i];
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IPreCrime } from "./interfaces/IPreCrime.sol";
import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "./interfaces/IOAppPreCrimeSimulator.sol";
/**
* @title OAppPreCrimeSimulator
* @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
*/
abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {
// The address of the preCrime implementation.
address public preCrime;
/**
* @dev Retrieves the address of the OApp contract.
* @return The address of the OApp contract.
*
* @dev The simulator contract is the base contract for the OApp by default.
* @dev If the simulator is a separate contract, override this function.
*/
function oApp() external view virtual returns (address) {
return address(this);
}
/**
* @dev Sets the preCrime contract address.
* @param _preCrime The address of the preCrime contract.
*/
function setPreCrime(address _preCrime) public virtual onlyOwner {
preCrime = _preCrime;
emit PreCrimeSet(_preCrime);
}
/**
* @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.
* @param _packets An array of InboundPacket objects representing received packets to be delivered.
*
* @dev WARNING: MUST revert at the end with the simulation results.
* @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,
* WITHOUT actually executing them.
*/
function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {
for (uint256 i = 0; i < _packets.length; i++) {
InboundPacket calldata packet = _packets[i];
// Ignore packets that are not from trusted peers.
if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;
// @dev Because a verifier is calling this function, it doesnt have access to executor params:
// - address _executor
// - bytes calldata _extraData
// preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().
// They are instead stubbed to default values, address(0) and bytes("")
// @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,
// which would cause the revert to be ignored.
this.lzReceiveSimulate{ value: packet.value }(
packet.origin,
packet.guid,
packet.message,
packet.executor,
packet.extraData
);
}
// @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().
revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());
}
/**
* @dev Is effectively an internal function because msg.sender must be address(this).
* Allows resetting the call stack for 'internal' calls.
* @param _origin The origin information containing the source endpoint and sender address.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address on the src chain.
* - nonce: The nonce of the message.
* @param _guid The unique identifier of the packet.
* @param _message The message payload of the packet.
* @param _executor The executor address for the packet.
* @param _extraData Additional data for the packet.
*/
function lzReceiveSimulate(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable virtual {
// @dev Ensure ONLY can be called 'internally'.
if (msg.sender != address(this)) revert OnlySelf();
_lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
* @param _origin The origin information.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address from the src chain.
* - nonce: The nonce of the LayerZero message.
* @param _guid The GUID of the LayerZero message.
* @param _message The LayerZero message.
* @param _executor The address of the off-chain executor.
* @param _extraData Arbitrary data passed by the msg executor.
*
* @dev Enables the preCrime simulator to mock sending lzReceive() messages,
* routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
*/
function _lzReceiveSimulate(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual;
/**
* @dev checks if the specified peer is considered 'trusted' by the OApp.
* @param _eid The endpoint Id to check.
* @param _peer The peer to check.
* @return Whether the peer passed is considered 'trusted' by the OApp.
*/
function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { MessagingReceipt, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol";
/**
* @dev Struct representing token parameters for the OFT send() operation.
*/
struct SendParam {
uint32 dstEid; // Destination endpoint ID.
bytes32 to; // Recipient address.
uint256 amountLD; // Amount to send in local decimals.
uint256 minAmountLD; // Minimum amount to send in local decimals.
bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
bytes composeMsg; // The composed message for the send() operation.
bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}
/**
* @dev Struct representing OFT limit information.
* @dev These amounts can change dynamically and are up the specific oft implementation.
*/
struct OFTLimit {
uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.
uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.
}
/**
* @dev Struct representing OFT receipt information.
*/
struct OFTReceipt {
uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
// @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}
/**
* @dev Struct representing OFT fee details.
* @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.
*/
struct OFTFeeDetail {
int256 feeAmountLD; // Amount of the fee in local decimals.
string description; // Description of the fee.
}
/**
* @title IOFT
* @dev Interface for the OftChain (OFT) token.
* @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.
* @dev This specific interface ID is '0x02e49c2c'.
*/
interface IOFT {
// Custom error messages
error InvalidLocalDecimals();
error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);
// Events
event OFTSent(
bytes32 indexed guid, // GUID of the OFT message.
uint32 dstEid, // Destination Endpoint ID.
address indexed fromAddress, // Address of the sender on the src chain.
uint256 amountSentLD, // Amount of tokens sent in local decimals.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
event OFTReceived(
bytes32 indexed guid, // GUID of the OFT message.
uint32 srcEid, // Source Endpoint ID.
address indexed toAddress, // Address of the recipient on the dst chain.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
/**
* @notice Retrieves interfaceID and the version of the OFT.
* @return interfaceId The interface ID.
* @return version The version.
*
* @dev interfaceId: This specific interface ID is '0x02e49c2c'.
* @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
* @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
* ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
*/
function oftVersion() external view returns (bytes4 interfaceId, uint64 version);
/**
* @notice Retrieves the address of the token associated with the OFT.
* @return token The address of the ERC20 token implementation.
*/
function token() external view returns (address);
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev Allows things like wallet implementers to determine integration requirements,
* without understanding the underlying token implementation.
*/
function approvalRequired() external view returns (bool);
/**
* @notice Retrieves the shared decimals of the OFT.
* @return sharedDecimals The shared decimals of the OFT.
*/
function sharedDecimals() external view returns (uint8);
/**
* @notice Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.
* @param _sendParam The parameters for the send operation.
* @return limit The OFT limit information.
* @return oftFeeDetails The details of OFT fees.
* @return receipt The OFT receipt information.
*/
function quoteOFT(
SendParam calldata _sendParam
) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);
/**
* @notice Provides a quote for the send() operation.
* @param _sendParam The parameters for the send() operation.
* @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
* @return fee The calculated LayerZero messaging fee from the send() operation.
*
* @dev MessagingFee: LayerZero msg fee
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
*/
function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);
/**
* @notice Executes the send() operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The fee information supplied by the caller.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds from fees etc. on the src.
* @return receipt The LayerZero messaging receipt from the send() operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory, OFTReceipt memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library OFTComposeMsgCodec {
// Offset constants for decoding composed messages
uint8 private constant NONCE_OFFSET = 8;
uint8 private constant SRC_EID_OFFSET = 12;
uint8 private constant AMOUNT_LD_OFFSET = 44;
uint8 private constant COMPOSE_FROM_OFFSET = 76;
/**
* @dev Encodes a OFT composed message.
* @param _nonce The nonce value.
* @param _srcEid The source endpoint ID.
* @param _amountLD The amount in local decimals.
* @param _composeMsg The composed message.
* @return _msg The encoded Composed message.
*/
function encode(
uint64 _nonce,
uint32 _srcEid,
uint256 _amountLD,
bytes memory _composeMsg // 0x[composeFrom][composeMsg]
) internal pure returns (bytes memory _msg) {
_msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
}
/**
* @dev Retrieves the nonce for the composed message.
* @param _msg The message.
* @return The nonce value.
*/
function nonce(bytes calldata _msg) internal pure returns (uint64) {
return uint64(bytes8(_msg[:NONCE_OFFSET]));
}
/**
* @dev Retrieves the source endpoint ID for the composed message.
* @param _msg The message.
* @return The source endpoint ID.
*/
function srcEid(bytes calldata _msg) internal pure returns (uint32) {
return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
}
/**
* @dev Retrieves the amount in local decimals from the composed message.
* @param _msg The message.
* @return The amount in local decimals.
*/
function amountLD(bytes calldata _msg) internal pure returns (uint256) {
return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
}
/**
* @dev Retrieves the composeFrom value from the composed message.
* @param _msg The message.
* @return The composeFrom value.
*/
function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
}
/**
* @dev Retrieves the composed message.
* @param _msg The message.
* @return The composed message.
*/
function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
return _msg[COMPOSE_FROM_OFFSET:];
}
/**
* @dev Converts an address to bytes32.
* @param _addr The address to convert.
* @return The bytes32 representation of the address.
*/
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
/**
* @dev Converts bytes32 to an address.
* @param _b The bytes32 value to convert.
* @return The address representation of bytes32.
*/
function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
return address(uint160(uint256(_b)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library OFTMsgCodec {
// Offset constants for encoding and decoding OFT messages
uint8 private constant SEND_TO_OFFSET = 32;
uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;
/**
* @dev Encodes an OFT LayerZero message.
* @param _sendTo The recipient address.
* @param _amountShared The amount in shared decimals.
* @param _composeMsg The composed message.
* @return _msg The encoded message.
* @return hasCompose A boolean indicating whether the message has a composed payload.
*/
function encode(
bytes32 _sendTo,
uint64 _amountShared,
bytes memory _composeMsg
) internal view returns (bytes memory _msg, bool hasCompose) {
hasCompose = _composeMsg.length > 0;
// @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.
_msg = hasCompose
? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)
: abi.encodePacked(_sendTo, _amountShared);
}
/**
* @dev Checks if the OFT message is composed.
* @param _msg The OFT message.
* @return A boolean indicating whether the message is composed.
*/
function isComposed(bytes calldata _msg) internal pure returns (bool) {
return _msg.length > SEND_AMOUNT_SD_OFFSET;
}
/**
* @dev Retrieves the recipient address from the OFT message.
* @param _msg The OFT message.
* @return The recipient address.
*/
function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
return bytes32(_msg[:SEND_TO_OFFSET]);
}
/**
* @dev Retrieves the amount in shared decimals from the OFT message.
* @param _msg The OFT message.
* @return The amount in shared decimals.
*/
function amountSD(bytes calldata _msg) internal pure returns (uint64) {
return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));
}
/**
* @dev Retrieves the composed message from the OFT message.
* @param _msg The OFT message.
* @return The composed message.
*/
function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
return _msg[SEND_AMOUNT_SD_OFFSET:];
}
/**
* @dev Converts an address to bytes32.
* @param _addr The address to convert.
* @return The bytes32 representation of the address.
*/
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
/**
* @dev Converts bytes32 to an address.
* @param _b The bytes32 value to convert.
* @return The address representation of bytes32.
*/
function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
return address(uint160(uint256(_b)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IOFT, OFTCore } from "./OFTCore.sol";
/**
* @title OFT Contract
* @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.
*/
abstract contract OFT is OFTCore, ERC20 {
/**
* @dev Constructor for the OFT contract.
* @param _name The name of the OFT.
* @param _symbol The symbol of the OFT.
* @param _lzEndpoint The LayerZero endpoint address.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate
) ERC20(_name, _symbol) OFTCore(decimals(), _lzEndpoint, _delegate) {}
/**
* @dev Retrieves the address of the underlying ERC20 implementation.
* @return The address of the OFT token.
*
* @dev In the case of OFT, address(this) and erc20 are the same contract.
*/
function token() public view returns (address) {
return address(this);
}
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev In the case of OFT where the contract IS the token, approval is NOT required.
*/
function approvalRequired() external pure virtual returns (bool) {
return false;
}
/**
* @dev Burns tokens from the sender's specified balance.
* @param _from The address to debit the tokens from.
* @param _amountLD The amount of tokens to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination chain ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
(amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);
// @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90,
// therefore amountSentLD CAN differ from amountReceivedLD.
// @dev Default OFT burns on src.
_burn(_from, amountSentLD);
}
/**
* @dev Credits tokens to the specified address.
* @param _to The address to credit the tokens to.
* @param _amountLD The amount of tokens to credit in local decimals.
* @dev _srcEid The source chain ID.
* @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 /*_srcEid*/
) internal virtual override returns (uint256 amountReceivedLD) {
if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0)
// @dev Default OFT mints on dst.
_mint(_to, _amountLD);
// @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD.
return _amountLD;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IOFT, OFTCore } from "./OFTCore.sol";
/**
* @title OFTAdapter Contract
* @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
*
* @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
* @dev WARNING: ONLY 1 of these should exist for a given global mesh,
* unless you make a NON-default implementation of OFT and needs to be done very carefully.
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
*/
abstract contract OFTAdapter is OFTCore {
using SafeERC20 for IERC20;
IERC20 internal immutable innerToken;
/**
* @dev Constructor for the OFTAdapter contract.
* @param _token The address of the ERC-20 token to be adapted.
* @param _lzEndpoint The LayerZero endpoint address.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(
address _token,
address _lzEndpoint,
address _delegate
) OFTCore(IERC20Metadata(_token).decimals(), _lzEndpoint, _delegate) {
innerToken = IERC20(_token);
}
/**
* @dev Retrieves the address of the underlying ERC20 implementation.
* @return The address of the adapted ERC-20 token.
*
* @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract.
*/
function token() public view returns (address) {
return address(innerToken);
}
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev In the case of default OFTAdapter, approval is required.
* @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval.
*/
function approvalRequired() external pure virtual returns (bool) {
return true;
}
/**
* @dev Locks tokens from the sender's specified balance in this contract.
* @param _from The address to debit from.
* @param _amountLD The amount of tokens to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination chain ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*
* @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract.
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountReceivedLD.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
(amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);
// @dev Lock tokens by moving them into this contract from the caller.
innerToken.safeTransferFrom(_from, address(this), amountSentLD);
}
/**
* @dev Credits tokens to the specified address.
* @param _to The address to credit the tokens to.
* @param _amountLD The amount of tokens to credit in local decimals.
* @dev _srcEid The source chain ID.
* @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
*
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountReceivedLD.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 /*_srcEid*/
) internal virtual override returns (uint256 amountReceivedLD) {
// @dev Unlock the tokens and transfer to the recipient.
innerToken.safeTransfer(_to, _amountLD);
// @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD.
return _amountLD;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { OApp, Origin } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { OAppOptionsType3 } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
import { IOAppMsgInspector } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppMsgInspector.sol";
import { OAppPreCrimeSimulator } from "@layerzerolabs/oapp-evm/contracts/precrime/OAppPreCrimeSimulator.sol";
import { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from "./interfaces/IOFT.sol";
import { OFTMsgCodec } from "./libs/OFTMsgCodec.sol";
import { OFTComposeMsgCodec } from "./libs/OFTComposeMsgCodec.sol";
/**
* @title OFTCore
* @dev Abstract contract for the OftChain (OFT) token.
*/
abstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {
using OFTMsgCodec for bytes;
using OFTMsgCodec for bytes32;
// @notice Provides a conversion rate when swapping between denominations of SD and LD
// - shareDecimals == SD == shared Decimals
// - localDecimals == LD == local decimals
// @dev Considers that tokens have different decimal amounts on various chains.
// @dev eg.
// For a token
// - locally with 4 decimals --> 1.2345 => uint(12345)
// - remotely with 2 decimals --> 1.23 => uint(123)
// - The conversion rate would be 10 ** (4 - 2) = 100
// @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote,
// you can only display 1.23 -> uint(123).
// @dev To preserve the dust that would otherwise be lost on that conversion,
// we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh
uint256 public immutable decimalConversionRate;
// @notice Msg types that are used to identify the various OFT operations.
// @dev This can be extended in child contracts for non-default oft operations
// @dev These values are used in things like combineOptions() in OAppOptionsType3.sol.
uint16 public constant SEND = 1;
uint16 public constant SEND_AND_CALL = 2;
// Address of an optional contract to inspect both 'message' and 'options'
address public msgInspector;
event MsgInspectorSet(address inspector);
/**
* @dev Constructor.
* @param _localDecimals The decimals of the token on the local chain (this chain).
* @param _endpoint The address of the LayerZero endpoint.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) {
if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals();
decimalConversionRate = 10 ** (_localDecimals - sharedDecimals());
}
/**
* @notice Retrieves interfaceID and the version of the OFT.
* @return interfaceId The interface ID.
* @return version The version.
*
* @dev interfaceId: This specific interface ID is '0x02e49c2c'.
* @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
* @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
* ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
*/
function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {
return (type(IOFT).interfaceId, 1);
}
/**
* @dev Retrieves the shared decimals of the OFT.
* @return The shared decimals of the OFT.
*
* @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap
* Lowest common decimal denominator between chains.
* Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).
* For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller.
* ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615
*/
function sharedDecimals() public view virtual returns (uint8) {
return 6;
}
/**
* @dev Sets the message inspector address for the OFT.
* @param _msgInspector The address of the message inspector.
*
* @dev This is an optional contract that can be used to inspect both 'message' and 'options'.
* @dev Set it to address(0) to disable it, or set it to a contract address to enable it.
*/
function setMsgInspector(address _msgInspector) public virtual onlyOwner {
msgInspector = _msgInspector;
emit MsgInspectorSet(_msgInspector);
}
/**
* @notice Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.
* @param _sendParam The parameters for the send operation.
* @return oftLimit The OFT limit information.
* @return oftFeeDetails The details of OFT fees.
* @return oftReceipt The OFT receipt information.
*/
function quoteOFT(
SendParam calldata _sendParam
)
external
view
virtual
returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)
{
uint256 minAmountLD = 0; // Unused in the default implementation.
uint256 maxAmountLD = IERC20(this.token()).totalSupply(); // Unused in the default implementation.
oftLimit = OFTLimit(minAmountLD, maxAmountLD);
// Unused in the default implementation; reserved for future complex fee details.
oftFeeDetails = new OFTFeeDetail[](0);
// @dev This is the same as the send() operation, but without the actual send.
// - amountSentLD is the amount in local decimals that would be sent from the sender.
// - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.
// @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.
(uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(
_sendParam.amountLD,
_sendParam.minAmountLD,
_sendParam.dstEid
);
oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
}
/**
* @notice Provides a quote for the send() operation.
* @param _sendParam The parameters for the send() operation.
* @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
* @return msgFee The calculated LayerZero messaging fee from the send() operation.
*
* @dev MessagingFee: LayerZero msg fee
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
*/
function quoteSend(
SendParam calldata _sendParam,
bool _payInLzToken
) external view virtual returns (MessagingFee memory msgFee) {
// @dev mock the amount to receive, this is the same operation used in the send().
// The quote is as similar as possible to the actual send() operation.
(, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);
// @dev Builds the options and OFT message to quote in the endpoint.
(bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
// @dev Calculates the LayerZero fee for the send() operation.
return _quote(_sendParam.dstEid, message, options, _payInLzToken);
}
/**
* @dev Executes the send operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The calculated fee for the send() operation.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds.
* @return msgReceipt The receipt for the send operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
return _send(_sendParam, _fee, _refundAddress);
}
/**
* @dev Internal function to execute the send operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The calculated fee for the send() operation.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds.
* @return msgReceipt The receipt for the send operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function _send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) internal virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
// @dev Applies the token transfers regarding this send() operation.
// - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.
// - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.
(uint256 amountSentLD, uint256 amountReceivedLD) = _debit(
msg.sender,
_sendParam.amountLD,
_sendParam.minAmountLD,
_sendParam.dstEid
);
// @dev Builds the options and OFT message to quote in the endpoint.
(bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
// @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.
msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
// @dev Formulate the OFT receipt.
oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);
}
/**
* @dev Internal function to build the message and options.
* @param _sendParam The parameters for the send() operation.
* @param _amountLD The amount in local decimals.
* @return message The encoded message.
* @return options The encoded options.
*/
function _buildMsgAndOptions(
SendParam calldata _sendParam,
uint256 _amountLD
) internal view virtual returns (bytes memory message, bytes memory options) {
bool hasCompose;
// @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is.
(message, hasCompose) = OFTMsgCodec.encode(
_sendParam.to,
_toSD(_amountLD),
// @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote.
// EVEN if you dont require an arbitrary payload to be sent... eg. '0x01'
_sendParam.composeMsg
);
// @dev Change the msg type depending if its composed or not.
uint16 msgType = hasCompose ? SEND_AND_CALL : SEND;
// @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3.
options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);
// @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.
// @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean
address inspector = msgInspector; // caches the msgInspector to avoid potential double storage read
if (inspector != address(0)) IOAppMsgInspector(inspector).inspect(message, options);
}
/**
* @dev Internal function to handle the receive on the LayerZero endpoint.
* @param _origin The origin information.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address from the src chain.
* - nonce: The nonce of the LayerZero message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The encoded message.
* @dev _executor The address of the executor.
* @dev _extraData Additional data.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address /*_executor*/, // @dev unused in the default implementation.
bytes calldata /*_extraData*/ // @dev unused in the default implementation.
) internal virtual override {
// @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)
// Thus everything is bytes32() encoded in flight.
address toAddress = _message.sendTo().bytes32ToAddress();
// @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals
uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);
if (_message.isComposed()) {
// @dev Proprietary composeMsg format for the OFT.
bytes memory composeMsg = OFTComposeMsgCodec.encode(
_origin.nonce,
_origin.srcEid,
amountReceivedLD,
_message.composeMsg()
);
// @dev Stores the lzCompose payload that will be executed in a separate tx.
// Standardizes functionality for executing arbitrary contract invocation on some non-evm chains.
// @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed.
// @dev The index is used when a OApp needs to compose multiple msgs on lzReceive.
// For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0.
endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg);
}
emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);
}
/**
* @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
* @param _origin The origin information.
* - srcEid: The source chain endpoint ID.
* - sender: The sender address from the src chain.
* - nonce: The nonce of the LayerZero message.
* @param _guid The unique identifier for the received LayerZero message.
* @param _message The LayerZero message.
* @param _executor The address of the off-chain executor.
* @param _extraData Arbitrary data passed by the msg executor.
*
* @dev Enables the preCrime simulator to mock sending lzReceive() messages,
* routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
*/
function _lzReceiveSimulate(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) internal virtual override {
_lzReceive(_origin, _guid, _message, _executor, _extraData);
}
/**
* @dev Check if the peer is considered 'trusted' by the OApp.
* @param _eid The endpoint ID to check.
* @param _peer The peer to check.
* @return Whether the peer passed is considered 'trusted' by the OApp.
*
* @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source.
*/
function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {
return peers[_eid] == _peer;
}
/**
* @dev Internal function to remove dust from the given local decimal amount.
* @param _amountLD The amount in local decimals.
* @return amountLD The amount after removing dust.
*
* @dev Prevents the loss of dust when moving amounts between chains with different decimals.
* @dev eg. uint(123) with a conversion rate of 100 becomes uint(100).
*/
function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) {
return (_amountLD / decimalConversionRate) * decimalConversionRate;
}
/**
* @dev Internal function to convert an amount from shared decimals into local decimals.
* @param _amountSD The amount in shared decimals.
* @return amountLD The amount in local decimals.
*/
function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) {
return _amountSD * decimalConversionRate;
}
/**
* @dev Internal function to convert an amount from local decimals into shared decimals.
* @param _amountLD The amount in local decimals.
* @return amountSD The amount in shared decimals.
*/
function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {
return uint64(_amountLD / decimalConversionRate);
}
/**
* @dev Internal function to mock the amount mutation from a OFT debit() operation.
* @param _amountLD The amount to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @dev _dstEid The destination endpoint ID.
* @return amountSentLD The amount sent, in local decimals.
* @return amountReceivedLD The amount to be received on the remote chain, in local decimals.
*
* @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.
*/
function _debitView(
uint256 _amountLD,
uint256 _minAmountLD,
uint32 /*_dstEid*/
) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
// @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.
amountSentLD = _removeDust(_amountLD);
// @dev The amount to send is the same as amount received in the default implementation.
amountReceivedLD = amountSentLD;
// @dev Check for slippage.
if (amountReceivedLD < _minAmountLD) {
revert SlippageExceeded(amountReceivedLD, _minAmountLD);
}
}
/**
* @dev Internal function to perform a debit operation.
* @param _from The address to debit.
* @param _amountLD The amount to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination endpoint ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*
* @dev Defined here but are intended to be overriden depending on the OFT implementation.
* @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD);
/**
* @dev Internal function to perform a credit operation.
* @param _to The address to credit.
* @param _amountLD The amount to credit in local decimals.
* @param _srcEid The source endpoint ID.
* @return amountReceivedLD The amount ACTUALLY received in local decimals.
*
* @dev Defined here but are intended to be overriden depending on the OFT implementation.
* @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 _srcEid
) internal virtual returns (uint256 amountReceivedLD);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* Both values are immutable: they can only be set once during construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OFTAdapter } from "@layerzerolabs/oft-evm/contracts/OFTAdapter.sol";
/**
* @title OFTAdapter Contract
* @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
*
* @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
* @dev WARNING: ONLY 1 of these should exist for a given global mesh,
* unless you make a NON-default implementation of OFT and needs to be done very carefully.
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
* IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
* a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
*/
contract RektOFTAdapter is OFTAdapter {
constructor(
address _token,
address _lzEndpoint,
address _delegate
) OFTAdapter(_token, _lzEndpoint, _delegate) Ownable(_delegate) {}
/**
* @dev Retrieves the shared decimals of the OFT.
* @return The shared decimals of the OFT.
*
* @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap
* Lowest common decimal denominator between chains.
* Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).
* Our token exceeds this totalSupply(420,690,000,000,000 ethers), we will need to override the sharedDecimals function with something smaller.
* 4 sharedDecimals would be 1,844,674,407,370,955.1615
*/
function sharedDecimals() public pure override returns (uint8) {
return 4;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_lzEndpoint","type":"address"},{"internalType":"address","name":"_delegate","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"inspector","type":"address"}],"name":"MsgInspectorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"srcEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"name":"OFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"preCrimeAddress","type":"address"}],"name":"PreCrimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"approvalRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"uint16","name":"_msgType","type":"uint16"},{"internalType":"bytes","name":"_extraOptions","type":"bytes"}],"name":"combineOptions","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalConversionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"isComposeMsgSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"isPeer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"},{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct InboundPacket[]","name":"_packets","type":"tuple[]"}],"name":"lzReceiveAndRevert","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceiveSimulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"msgInspector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oApp","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"oftVersion","outputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"},{"internalType":"uint64","name":"version","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preCrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"}],"name":"quoteOFT","outputs":[{"components":[{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"uint256","name":"maxAmountLD","type":"uint256"}],"internalType":"struct OFTLimit","name":"oftLimit","type":"tuple"},{"components":[{"internalType":"int256","name":"feeAmountLD","type":"int256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct OFTFeeDetail[]","name":"oftFeeDetails","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quoteSend","outputs":[{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"msgFee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"dstEid","type":"uint32"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"},{"internalType":"bytes","name":"extraOptions","type":"bytes"},{"internalType":"bytes","name":"composeMsg","type":"bytes"},{"internalType":"bytes","name":"oftCmd","type":"bytes"}],"internalType":"struct SendParam","name":"_sendParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"_fee","type":"tuple"},{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"send","outputs":[{"components":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"components":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"internalType":"struct MessagingFee","name":"fee","type":"tuple"}],"internalType":"struct MessagingReceipt","name":"msgReceipt","type":"tuple"},{"components":[{"internalType":"uint256","name":"amountSentLD","type":"uint256"},{"internalType":"uint256","name":"amountReceivedLD","type":"uint256"}],"internalType":"struct OFTReceipt","name":"oftReceipt","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_msgInspector","type":"address"}],"name":"setMsgInspector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"bytes32","name":"_peer","type":"bytes32"}],"name":"setPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_preCrime","type":"address"}],"name":"setPreCrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharedDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c060405234801561001057600080fd5b5060405161370738038061370783398101604081905261002f916102ab565b83838383838360128484818181818d6001600160a01b03811661006c57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61007581610181565b506001600160a01b0380831660805281166100a357604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b1580156100ea57600080fd5b505af11580156100fe573d6000803e3d6000fd5b50505050505050506101146101d160201b60201c565b60ff168360ff16101561013a576040516301e9714b60e41b815260040160405180910390fd5b61014560048461034b565b61015090600a610451565b60a0525060089150610164905083826104f0565b50600961017182826104f0565b50505050505050505050506105ae565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600490565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126101fd57600080fd5b81516001600160401b03811115610216576102166101d6565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610244576102446101d6565b60405281815283820160200185101561025c57600080fd5b60005b8281101561027b5760208186018101518383018201520161025f565b506000918101602001919091529392505050565b80516001600160a01b03811681146102a657600080fd5b919050565b600080600080608085870312156102c157600080fd5b84516001600160401b038111156102d757600080fd5b6102e3878288016101ec565b602087015190955090506001600160401b0381111561030157600080fd5b61030d878288016101ec565b93505061031c6040860161028f565b915061032a6060860161028f565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111561036457610364610335565b92915050565b6001815b60018411156103a55780850481111561038957610389610335565b600184161561039757908102905b60019390931c92800261036e565b935093915050565b6000826103bc57506001610364565b816103c957506000610364565b81600181146103df57600281146103e957610405565b6001915050610364565b60ff8411156103fa576103fa610335565b50506001821b610364565b5060208310610133831016604e8410600b8410161715610428575081810a610364565b610435600019848461036a565b806000190482111561044957610449610335565b029392505050565b600061046060ff8416836103ad565b9392505050565b600181811c9082168061047b57607f821691505b60208210810361049b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156104eb57806000526020600020601f840160051c810160208510156104c85750805b601f840160051c820191505b818110156104e857600081556001016104d4565b50505b505050565b81516001600160401b03811115610509576105096101d6565b61051d816105178454610467565b846104a1565b6020601f82116001811461055157600083156105395750848201515b600019600385901b1c1916600184901b1784556104e8565b600084815260208120601f198516915b828110156105815787850151825560209485019460019092019101610561565b508482101561059f5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60805160a0516130ee6106196000396000818161061e01528181611aa101528181611b160152611d1a0152600081816104dd01528181610a4d0152818161109d015281816113140152818161167f01528181611e1201528181611f82015261203901526130ee6000f3fe6080604052600436106102515760003560e01c80637d25a05e11610139578063bb0b6a53116100b6578063d045a0dc1161007a578063d045a0dc14610755578063d424388514610768578063dd62ed3e14610788578063f2fde38b146107ce578063fc0c546a14610461578063ff7bd03d146107ee57600080fd5b8063bb0b6a53146106b4578063bc70b354146106e1578063bd815db014610701578063c7c7f5b314610714578063ca5eb5e11461073557600080fd5b8063963efcaa116100fd578063963efcaa1461060c5780639f68b96414610640578063a9059cbb14610654578063b731ea0a14610674578063b98bd0701461069457600080fd5b80637d25a05e1461056a57806382413eac146105a5578063857749b0146105c55780638da5cb5b146105d957806395d89b41146105f757600080fd5b806323b872dd116101d25780635535d461116101965780635535d461146104745780635a0dfe4d146104945780635e280f11146104cb5780636fc1b31e146104ff57806370a082311461051f578063715018a61461055557600080fd5b806323b872dd146103d2578063313ce567146103f25780633400288b146104145780633b6f743b1461043457806352ae28791461046157600080fd5b8063134d4f2511610219578063134d4f251461032d578063156a0d0f1461035557806317442b701461037c57806318160ddd1461039e5780631f5e1334146103bd57600080fd5b806306fdde0314610256578063095ea7b3146102815780630d35b415146102b1578063111ecdad146102e057806313137d6514610318575b600080fd5b34801561026257600080fd5b5061026b61080e565b60405161027891906121b1565b60405180910390f35b34801561028d57600080fd5b506102a161029c3660046121d9565b6108a0565b6040519015158152602001610278565b3480156102bd57600080fd5b506102d16102cc36600461221d565b6108ba565b60405161027893929190612251565b3480156102ec57600080fd5b50600454610300906001600160a01b031681565b6040516001600160a01b039091168152602001610278565b61032b610326366004612348565b610a4b565b005b34801561033957600080fd5b50610342600281565b60405161ffff9091168152602001610278565b34801561036157600080fd5b506040805162b9270b60e21b81526001602082015201610278565b34801561038857600080fd5b5060408051600181526002602082015201610278565b3480156103aa57600080fd5b506007545b604051908152602001610278565b3480156103c957600080fd5b50610342600181565b3480156103de57600080fd5b506102a16103ed3660046123e9565b610b0b565b3480156103fe57600080fd5b5060125b60405160ff9091168152602001610278565b34801561042057600080fd5b5061032b61042f366004612443565b610b31565b34801561044057600080fd5b5061045461044f36600461246d565b610b47565b60405161027891906124be565b34801561046d57600080fd5b5030610300565b34801561048057600080fd5b5061026b61048f3660046124e7565b610bae565b3480156104a057600080fd5b506102a16104af366004612443565b63ffffffff919091166000908152600160205260409020541490565b3480156104d757600080fd5b506103007f000000000000000000000000000000000000000000000000000000000000000081565b34801561050b57600080fd5b5061032b61051a36600461251a565b610c53565b34801561052b57600080fd5b506103af61053a36600461251a565b6001600160a01b031660009081526005602052604090205490565b34801561056157600080fd5b5061032b610cb0565b34801561057657600080fd5b5061058d610585366004612443565b600092915050565b6040516001600160401b039091168152602001610278565b3480156105b157600080fd5b506102a16105c0366004612537565b610cc4565b3480156105d157600080fd5b506004610402565b3480156105e557600080fd5b506000546001600160a01b0316610300565b34801561060357600080fd5b5061026b610cd9565b34801561061857600080fd5b506103af7f000000000000000000000000000000000000000000000000000000000000000081565b34801561064c57600080fd5b5060006102a1565b34801561066057600080fd5b506102a161066f3660046121d9565b610ce8565b34801561068057600080fd5b50600254610300906001600160a01b031681565b3480156106a057600080fd5b5061032b6106af3660046125e1565b610cf6565b3480156106c057600080fd5b506103af6106cf366004612622565b60016020526000908152604090205481565b3480156106ed57600080fd5b5061026b6106fc36600461263d565b610d10565b61032b61070f3660046125e1565b610eb8565b61072761072236600461269d565b611042565b60405161027892919061270a565b34801561074157600080fd5b5061032b61075036600461251a565b611076565b61032b610763366004612348565b6110fc565b34801561077457600080fd5b5061032b61078336600461251a565b61112b565b34801561079457600080fd5b506103af6107a336600461275c565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b3480156107da57600080fd5b5061032b6107e936600461251a565b611181565b3480156107fa57600080fd5b506102a161080936600461278a565b6111bf565b60606008805461081d906127a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610849906127a6565b80156108965780601f1061086b57610100808354040283529160200191610896565b820191906000526020600020905b81548152906001019060200180831161087957829003601f168201915b5050505050905090565b6000336108ae8185856111f5565b60019150505b92915050565b604080518082019091526000808252602082015260606108ed604051806040016040528060008152602001600081525090565b600080306001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095291906127da565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b391906127f7565b60408051808201825284815260208082018490528251600080825291810190935290975091925090610a08565b6040805180820190915260008152606060208201528152602001906001900390816109e05790505b509350600080610a2d604089013560608a0135610a2860208c018c612622565b611207565b60408051808201909152918252602082015296989597505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610a9b576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610ab590610ab0908a612622565b611243565b14610af357610ac76020880188612622565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610a92565b610b028787878787878761127f565b50505050505050565b600033610b198582856113e6565b610b24858585611465565b60019150505b9392505050565b610b396114c4565b610b4382826114f1565b5050565b60408051808201909152600080825260208201526000610b7760408501356060860135610a286020880188612622565b915050600080610b878684611546565b9092509050610ba4610b9c6020880188612622565b838388611669565b9695505050505050565b600360209081526000928352604080842090915290825290208054610bd2906127a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfe906127a6565b8015610c4b5780601f10610c2057610100808354040283529160200191610c4b565b820191906000526020600020905b815481529060010190602001808311610c2e57829003601f168201915b505050505081565b610c5b6114c4565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b610cb86114c4565b610cc2600061174a565b565b6001600160a01b03811630145b949350505050565b60606009805461081d906127a6565b6000336108ae818585611465565b610cfe6114c4565b610b43610d0b82846128c7565b61179a565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610d44906127a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610d70906127a6565b8015610dbd5780601f10610d9257610100808354040283529160200191610dbd565b820191906000526020600020905b815481529060010190602001808311610da057829003601f168201915b505050505090508051600003610e0d5783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610cd19350505050565b6000839003610e1d579050610cd1565b60028310610e9b57610e6484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506118a192505050565b80610e7284600281886129f0565b604051602001610e8493929190612a1a565b604051602081830303815290604052915050610cd1565b8383604051639a6d49cd60e01b8152600401610a92929190612a6b565b60005b81811015610fc15736838383818110610ed657610ed6612a7f565b9050602002810190610ee89190612a95565b9050610f1b610efa6020830183612622565b602083013563ffffffff919091166000908152600160205260409020541490565b610f255750610fb9565b3063d045a0dc60c08301358360a0810135610f44610100830183612ab6565b610f55610100890160e08a0161251a565b610f636101208a018a612ab6565b6040518963ffffffff1660e01b8152600401610f859796959493929190612b11565b6000604051808303818588803b158015610f9e57600080fd5b505af1158015610fb2573d6000803e3d6000fd5b5050505050505b600101610ebb565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611000573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110289190810190612b97565b604051638351eea760e01b8152600401610a9291906121b1565b61104a61211a565b60408051808201909152600080825260208201526110698585856118cd565b915091505b935093915050565b61107e6114c4565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b1580156110e157600080fd5b505af11580156110f5573d6000803e3d6000fd5b5050505050565b33301461111c5760405163029a949d60e31b815260040160405180910390fd5b610b0287878787878787610af3565b6111336114c4565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610ca5565b6111896114c4565b6001600160a01b0381166111b357604051631e4fbdf760e01b815260006004820152602401610a92565b6111bc8161174a565b50565b60006020820180359060019083906111d79086612622565b63ffffffff1681526020810191909152604001600020541492915050565b61120283838360016119c8565b505050565b60008061121385611a9d565b91508190508381101561106e576040516371c4efed60e01b81526004810182905260248101859052604401610a92565b63ffffffff8116600090815260016020526040812054806108b45760405163f6ff4fb760e01b815263ffffffff84166004820152602401610a92565b600061129161128e8787611ad4565b90565b905060006112bd826112ab6112a68a8a611aec565b611b0f565b6112b860208d018d612622565b611b44565b905060288611156113845760006112fa6112dd60608c0160408d01612c04565b6112ea60208d018d612622565b846112f58c8c611b6c565b611bb7565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906113509086908d906000908790600401612c21565b600060405180830381600087803b15801561136a57600080fd5b505af115801561137e573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c6113bd60208d018d612622565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b0383811660009081526006602090815260408083209386168352929052205460001981101561145f578181101561145057604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610a92565b61145f848484840360006119c8565b50505050565b6001600160a01b03831661148f57604051634b637e8f60e11b815260006004820152602401610a92565b6001600160a01b0382166114b95760405163ec442f0560e01b815260006004820152602401610a92565b611202838383611be9565b6000546001600160a01b03163314610cc25760405163118cdaa760e01b8152336004820152602401610a92565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b60608060006115a3856020013561155c86611d13565b61156960a0890189612ab6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d3f92505050565b90935090506000816115b65760016115b9565b60025b90506115d96115cb6020880188612622565b826106fc60808a018a612ab6565b6004549093506001600160a01b0316801561165f5760405163043a78eb60e01b81526001600160a01b0382169063043a78eb9061161c9088908890600401612c52565b602060405180830381865afa158015611639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165d9190612c77565b505b5050509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff1681526020016116cc89611243565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611701929190612c94565b6040805180830381865afa15801561171d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117419190612d3e565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611871576117cc8282815181106117bb576117bb612a7f565b6020026020010151604001516118a1565b8181815181106117de576117de612a7f565b6020026020010151604001516003600084848151811061180057611800612a7f565b60200260200101516000015163ffffffff1663ffffffff168152602001908152602001600020600084848151811061183a5761183a612a7f565b60200260200101516020015161ffff1661ffff16815260200190815260200160002090816118689190612da1565b5060010161179d565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610ca59190612e5f565b600281015161ffff8116600314610b435781604051639a6d49cd60e01b8152600401610a9291906121b1565b6118d561211a565b604080518082019091526000808252602082015260008061190c33604089013560608a013561190760208c018c612622565b611db9565b9150915060008061191d8984611546565b909250905061194961193260208b018b612622565b8383611943368d90038d018d612eef565b8b611ddf565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611997908d018d612622565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6001600160a01b0384166119f25760405163e602df0560e01b815260006004820152602401610a92565b6001600160a01b038316611a1c57604051634a1406b160e11b815260006004820152602401610a92565b6001600160a01b038085166000908152600660209081526040808320938716835292905220829055801561145f57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611a8f91815260200190565b60405180910390a350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000611aca8184612f38565b6108b49190612f5a565b6000611ae360208284866129f0565b610b2a91612f71565b6000611afc6028602084866129f0565b611b0591612f8f565b60c01c9392505050565b60006108b47f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416612f5a565b60006001600160a01b038416611b5a5761dead93505b611b648484611eea565b509092915050565b6060611b7b82602881866129f0565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b606084848484604051602001611bd09493929190612fc7565b6040516020818303038152906040529050949350505050565b6001600160a01b038316611c14578060076000828254611c099190613016565b90915550611c869050565b6001600160a01b03831660009081526005602052604090205481811015611c675760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610a92565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b038216611ca257600780548290039055611cc1565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611d0691815260200190565b60405180910390a3505050565b60006108b47f000000000000000000000000000000000000000000000000000000000000000083612f38565b8051606090151580611d88578484604051602001611d7492919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052611daf565b84843385604051602001611d9f9493929190613029565b6040516020818303038152906040525b9150935093915050565b600080611dc7858585611207565b9092509050611dd68683611f20565b94509492505050565b611de761211a565b6000611df68460000151611f56565b602085015190915015611e1057611e108460200151611f7e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001611e608c611243565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401611e9c929190612c94565b60806040518083038185885af1158015611eba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611edf919061306c565b979650505050505050565b6001600160a01b038216611f145760405163ec442f0560e01b815260006004820152602401610a92565b610b4360008383611be9565b6001600160a01b038216611f4a57604051634b637e8f60e11b815260006004820152602401610a92565b610b4382600083611be9565b6000813414611f7a576040516304fb820960e51b8152346004820152602401610a92565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200291906127da565b90506001600160a01b03811661202b576040516329b99a9560e11b815260040160405180910390fd5b6040805133602482018190527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0381811660448501526064808501889052855180860390910181526084909401909452602080840180516001600160e01b03166323b872dd60e01b1781528451610b4396881695899361145f93889360009283929091839182885af1806120cc576040513d6000823e3d81fd5b50506000513d915081156120e45780600114156120f1565b6001600160a01b0384163b155b1561145f57604051635274afe760e01b81526001600160a01b0385166004820152602401610a92565b60405180606001604052806000801916815260200160006001600160401b0316815260200161215c604051806040016040528060008152602001600081525090565b905290565b60005b8381101561217c578181015183820152602001612164565b50506000910152565b6000815180845261219d816020860160208601612161565b601f01601f19169290920160200192915050565b602081526000610b2a6020830184612185565b6001600160a01b03811681146111bc57600080fd5b600080604083850312156121ec57600080fd5b82356121f7816121c4565b946020939093013593505050565b600060e0828403121561221757600080fd5b50919050565b60006020828403121561222f57600080fd5b81356001600160401b0381111561224557600080fd5b610cd184828501612205565b8351815260208085015190820152600060a0820160a0604084015280855180835260c08501915060c08160051b86010192506020870160005b828110156122d25760bf1987860301845281518051865260208101519050604060208701526122bc6040870182612185565b955050602093840193919091019060010161228a565b5050855160608601525050602084015160808401529050610cd1565b60006060828403121561221757600080fd5b60008083601f84011261231257600080fd5b5081356001600160401b0381111561232957600080fd5b60208301915083602082850101111561234157600080fd5b9250929050565b600080600080600080600060e0888a03121561236357600080fd5b61236d89896122ee565b96506060880135955060808801356001600160401b0381111561238f57600080fd5b61239b8a828b01612300565b90965094505060a08801356123af816121c4565b925060c08801356001600160401b038111156123ca57600080fd5b6123d68a828b01612300565b989b979a50959850939692959293505050565b6000806000606084860312156123fe57600080fd5b8335612409816121c4565b92506020840135612419816121c4565b929592945050506040919091013590565b803563ffffffff8116811461243e57600080fd5b919050565b6000806040838503121561245657600080fd5b6121f78361242a565b80151581146111bc57600080fd5b6000806040838503121561248057600080fd5b82356001600160401b0381111561249657600080fd5b6124a285828601612205565b92505060208301356124b38161245f565b809150509250929050565b8151815260208083015190820152604081016108b4565b803561ffff8116811461243e57600080fd5b600080604083850312156124fa57600080fd5b6125038361242a565b9150612511602084016124d5565b90509250929050565b60006020828403121561252c57600080fd5b8135610b2a816121c4565b60008060008060a0858703121561254d57600080fd5b61255786866122ee565b935060608501356001600160401b0381111561257257600080fd5b61257e87828801612300565b9094509250506080850135612592816121c4565b939692955090935050565b60008083601f8401126125af57600080fd5b5081356001600160401b038111156125c657600080fd5b6020830191508360208260051b850101111561234157600080fd5b600080602083850312156125f457600080fd5b82356001600160401b0381111561260a57600080fd5b6126168582860161259d565b90969095509350505050565b60006020828403121561263457600080fd5b610b2a8261242a565b6000806000806060858703121561265357600080fd5b61265c8561242a565b935061266a602086016124d5565b925060408501356001600160401b0381111561268557600080fd5b61269187828801612300565b95989497509550505050565b600080600083850360808112156126b357600080fd5b84356001600160401b038111156126c957600080fd5b6126d587828801612205565b9450506040601f19820112156126ea57600080fd5b5060208401915060608401356126ff816121c4565b809150509250925092565b600060c082019050835182526001600160401b0360208501511660208301526040840151612745604084018280518252602090810151910152565b5082516080830152602083015160a0830152610b2a565b6000806040838503121561276f57600080fd5b823561277a816121c4565b915060208301356124b3816121c4565b60006060828403121561279c57600080fd5b610b2a83836122ee565b600181811c908216806127ba57607f821691505b60208210810361221757634e487b7160e01b600052602260045260246000fd5b6000602082840312156127ec57600080fd5b8151610b2a816121c4565b60006020828403121561280957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561284857612848612810565b60405290565b604080519081016001600160401b038111828210171561284857612848612810565b604051601f8201601f191681016001600160401b038111828210171561289857612898612810565b604052919050565b60006001600160401b038211156128b9576128b9612810565b50601f01601f191660200190565b60006001600160401b038311156128e0576128e0612810565b8260051b6128f060208201612870565b8481529083019060208101903683111561290957600080fd5b845b838110156129e65780356001600160401b0381111561292957600080fd5b8601606036829003121561293c57600080fd5b612944612826565b61294d8261242a565b815261295b602083016124d5565b602082015260408201356001600160401b0381111561297957600080fd5b919091019036601f83011261298d57600080fd5b81356129a061299b826128a0565b612870565b8181523660208386010111156129b557600080fd5b816020850160208301376000602083830101528060408401525050808552505060208301925060208101905061290b565b5095945050505050565b60008085851115612a0057600080fd5b83861115612a0d57600080fd5b5050820193919092039150565b60008451612a2c818460208901612161565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610cd1602083018486612a42565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112612aac57600080fd5b9190910192915050565b6000808335601e19843603018112612acd57600080fd5b8301803591506001600160401b03821115612ae757600080fd5b60200191503681900382131561234157600080fd5b6001600160401b03811681146111bc57600080fd5b63ffffffff612b1f8961242a565b1681526020888101359082015260006040890135612b3c81612afc565b6001600160401b03811660408401525087606083015260e06080830152612b6760e083018789612a42565b6001600160a01b03861660a084015282810360c0840152612b89818587612a42565b9a9950505050505050505050565b600060208284031215612ba957600080fd5b81516001600160401b03811115612bbf57600080fd5b8201601f81018413612bd057600080fd5b8051612bde61299b826128a0565b818152856020838501011115612bf357600080fd5b611741826020830160208601612161565b600060208284031215612c1657600080fd5b8135610b2a81612afc565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610ba46080830184612185565b604081526000612c656040830185612185565b82810360208401526117418185612185565b600060208284031215612c8957600080fd5b8151610b2a8161245f565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152612cca60e0840182612185565b90506060850151603f198483030160a0850152612ce78282612185565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215612d1f57600080fd5b612d2761284e565b825181526020928301519281019290925250919050565b600060408284031215612d5057600080fd5b610b2a8383612d0d565b601f82111561120257806000526020600020601f840160051c81016020851015612d815750805b601f840160051c820191505b818110156110f55760008155600101612d8d565b81516001600160401b03811115612dba57612dba612810565b612dce81612dc884546127a6565b84612d5a565b6020601f821160018114612e025760008315612dea5750848201515b600019600385901b1c1916600184901b1784556110f5565b600084815260208120601f198516915b82811015612e325787850151825560209485019460019092019101612e12565b5084821015612e505786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015612ee357603f19878603018452815163ffffffff815116865261ffff60208201511660208701526040810151905060606040870152612ecd6060870182612185565b9550506020938401939190910190600101612e87565b50929695505050505050565b60006040828403128015612f0257600080fd5b50612f0b61284e565b823581526020928301359281019290925250919050565b634e487b7160e01b600052601160045260246000fd5b600082612f5557634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176108b4576108b4612f22565b803560208310156108b457600019602084900360031b1b1692915050565b80356001600160c01b03198116906008841015612fc0576001600160c01b0319600885900360031b81901b82161691505b5092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161300681602c850160208701612161565b91909101602c0195945050505050565b808201808211156108b4576108b4612f22565b8481526001600160401b0360c01b8460c01b1660208201528260288201526000825161305c816048850160208701612161565b9190910160480195945050505050565b6000608082840312801561307f57600080fd5b50613088612826565b82518152602083015161309a81612afc565b60208201526130ac8460408501612d0d565b6040820152939250505056fea264697066735822122068198981facd40d56e4088c3bf4271ce2ed08ed24f71105748e8464517e41ecc64736f6c634300081e0033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa9000000000000000000000000ff2ddef995bf1de2df67612bda5f9901798580a2000000000000000000000000000000000000000000000000000000000000000452656b7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000452454b5400000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102515760003560e01c80637d25a05e11610139578063bb0b6a53116100b6578063d045a0dc1161007a578063d045a0dc14610755578063d424388514610768578063dd62ed3e14610788578063f2fde38b146107ce578063fc0c546a14610461578063ff7bd03d146107ee57600080fd5b8063bb0b6a53146106b4578063bc70b354146106e1578063bd815db014610701578063c7c7f5b314610714578063ca5eb5e11461073557600080fd5b8063963efcaa116100fd578063963efcaa1461060c5780639f68b96414610640578063a9059cbb14610654578063b731ea0a14610674578063b98bd0701461069457600080fd5b80637d25a05e1461056a57806382413eac146105a5578063857749b0146105c55780638da5cb5b146105d957806395d89b41146105f757600080fd5b806323b872dd116101d25780635535d461116101965780635535d461146104745780635a0dfe4d146104945780635e280f11146104cb5780636fc1b31e146104ff57806370a082311461051f578063715018a61461055557600080fd5b806323b872dd146103d2578063313ce567146103f25780633400288b146104145780633b6f743b1461043457806352ae28791461046157600080fd5b8063134d4f2511610219578063134d4f251461032d578063156a0d0f1461035557806317442b701461037c57806318160ddd1461039e5780631f5e1334146103bd57600080fd5b806306fdde0314610256578063095ea7b3146102815780630d35b415146102b1578063111ecdad146102e057806313137d6514610318575b600080fd5b34801561026257600080fd5b5061026b61080e565b60405161027891906121b1565b60405180910390f35b34801561028d57600080fd5b506102a161029c3660046121d9565b6108a0565b6040519015158152602001610278565b3480156102bd57600080fd5b506102d16102cc36600461221d565b6108ba565b60405161027893929190612251565b3480156102ec57600080fd5b50600454610300906001600160a01b031681565b6040516001600160a01b039091168152602001610278565b61032b610326366004612348565b610a4b565b005b34801561033957600080fd5b50610342600281565b60405161ffff9091168152602001610278565b34801561036157600080fd5b506040805162b9270b60e21b81526001602082015201610278565b34801561038857600080fd5b5060408051600181526002602082015201610278565b3480156103aa57600080fd5b506007545b604051908152602001610278565b3480156103c957600080fd5b50610342600181565b3480156103de57600080fd5b506102a16103ed3660046123e9565b610b0b565b3480156103fe57600080fd5b5060125b60405160ff9091168152602001610278565b34801561042057600080fd5b5061032b61042f366004612443565b610b31565b34801561044057600080fd5b5061045461044f36600461246d565b610b47565b60405161027891906124be565b34801561046d57600080fd5b5030610300565b34801561048057600080fd5b5061026b61048f3660046124e7565b610bae565b3480156104a057600080fd5b506102a16104af366004612443565b63ffffffff919091166000908152600160205260409020541490565b3480156104d757600080fd5b506103007f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa981565b34801561050b57600080fd5b5061032b61051a36600461251a565b610c53565b34801561052b57600080fd5b506103af61053a36600461251a565b6001600160a01b031660009081526005602052604090205490565b34801561056157600080fd5b5061032b610cb0565b34801561057657600080fd5b5061058d610585366004612443565b600092915050565b6040516001600160401b039091168152602001610278565b3480156105b157600080fd5b506102a16105c0366004612537565b610cc4565b3480156105d157600080fd5b506004610402565b3480156105e557600080fd5b506000546001600160a01b0316610300565b34801561060357600080fd5b5061026b610cd9565b34801561061857600080fd5b506103af7f00000000000000000000000000000000000000000000000000005af3107a400081565b34801561064c57600080fd5b5060006102a1565b34801561066057600080fd5b506102a161066f3660046121d9565b610ce8565b34801561068057600080fd5b50600254610300906001600160a01b031681565b3480156106a057600080fd5b5061032b6106af3660046125e1565b610cf6565b3480156106c057600080fd5b506103af6106cf366004612622565b60016020526000908152604090205481565b3480156106ed57600080fd5b5061026b6106fc36600461263d565b610d10565b61032b61070f3660046125e1565b610eb8565b61072761072236600461269d565b611042565b60405161027892919061270a565b34801561074157600080fd5b5061032b61075036600461251a565b611076565b61032b610763366004612348565b6110fc565b34801561077457600080fd5b5061032b61078336600461251a565b61112b565b34801561079457600080fd5b506103af6107a336600461275c565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b3480156107da57600080fd5b5061032b6107e936600461251a565b611181565b3480156107fa57600080fd5b506102a161080936600461278a565b6111bf565b60606008805461081d906127a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610849906127a6565b80156108965780601f1061086b57610100808354040283529160200191610896565b820191906000526020600020905b81548152906001019060200180831161087957829003601f168201915b5050505050905090565b6000336108ae8185856111f5565b60019150505b92915050565b604080518082019091526000808252602082015260606108ed604051806040016040528060008152602001600081525090565b600080306001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095291906127da565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b391906127f7565b60408051808201825284815260208082018490528251600080825291810190935290975091925090610a08565b6040805180820190915260008152606060208201528152602001906001900390816109e05790505b509350600080610a2d604089013560608a0135610a2860208c018c612622565b611207565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa96001600160a01b03163314610a9b576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610ab590610ab0908a612622565b611243565b14610af357610ac76020880188612622565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610a92565b610b028787878787878761127f565b50505050505050565b600033610b198582856113e6565b610b24858585611465565b60019150505b9392505050565b610b396114c4565b610b4382826114f1565b5050565b60408051808201909152600080825260208201526000610b7760408501356060860135610a286020880188612622565b915050600080610b878684611546565b9092509050610ba4610b9c6020880188612622565b838388611669565b9695505050505050565b600360209081526000928352604080842090915290825290208054610bd2906127a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfe906127a6565b8015610c4b5780601f10610c2057610100808354040283529160200191610c4b565b820191906000526020600020905b815481529060010190602001808311610c2e57829003601f168201915b505050505081565b610c5b6114c4565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d4414197906020015b60405180910390a150565b610cb86114c4565b610cc2600061174a565b565b6001600160a01b03811630145b949350505050565b60606009805461081d906127a6565b6000336108ae818585611465565b610cfe6114c4565b610b43610d0b82846128c7565b61179a565b63ffffffff8416600090815260036020908152604080832061ffff87168452909152812080546060929190610d44906127a6565b80601f0160208091040260200160405190810160405280929190818152602001828054610d70906127a6565b8015610dbd5780601f10610d9257610100808354040283529160200191610dbd565b820191906000526020600020905b815481529060010190602001808311610da057829003601f168201915b505050505090508051600003610e0d5783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610cd19350505050565b6000839003610e1d579050610cd1565b60028310610e9b57610e6484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506118a192505050565b80610e7284600281886129f0565b604051602001610e8493929190612a1a565b604051602081830303815290604052915050610cd1565b8383604051639a6d49cd60e01b8152600401610a92929190612a6b565b60005b81811015610fc15736838383818110610ed657610ed6612a7f565b9050602002810190610ee89190612a95565b9050610f1b610efa6020830183612622565b602083013563ffffffff919091166000908152600160205260409020541490565b610f255750610fb9565b3063d045a0dc60c08301358360a0810135610f44610100830183612ab6565b610f55610100890160e08a0161251a565b610f636101208a018a612ab6565b6040518963ffffffff1660e01b8152600401610f859796959493929190612b11565b6000604051808303818588803b158015610f9e57600080fd5b505af1158015610fb2573d6000803e3d6000fd5b5050505050505b600101610ebb565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611000573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110289190810190612b97565b604051638351eea760e01b8152600401610a9291906121b1565b61104a61211a565b60408051808201909152600080825260208201526110698585856118cd565b915091505b935093915050565b61107e6114c4565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa9169063ca5eb5e190602401600060405180830381600087803b1580156110e157600080fd5b505af11580156110f5573d6000803e3d6000fd5b5050505050565b33301461111c5760405163029a949d60e31b815260040160405180910390fd5b610b0287878787878787610af3565b6111336114c4565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610ca5565b6111896114c4565b6001600160a01b0381166111b357604051631e4fbdf760e01b815260006004820152602401610a92565b6111bc8161174a565b50565b60006020820180359060019083906111d79086612622565b63ffffffff1681526020810191909152604001600020541492915050565b61120283838360016119c8565b505050565b60008061121385611a9d565b91508190508381101561106e576040516371c4efed60e01b81526004810182905260248101859052604401610a92565b63ffffffff8116600090815260016020526040812054806108b45760405163f6ff4fb760e01b815263ffffffff84166004820152602401610a92565b600061129161128e8787611ad4565b90565b905060006112bd826112ab6112a68a8a611aec565b611b0f565b6112b860208d018d612622565b611b44565b905060288611156113845760006112fa6112dd60608c0160408d01612c04565b6112ea60208d018d612622565b846112f58c8c611b6c565b611bb7565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa91690637cb59012906113509086908d906000908790600401612c21565b600060405180830381600087803b15801561136a57600080fd5b505af115801561137e573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c6113bd60208d018d612622565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b0383811660009081526006602090815260408083209386168352929052205460001981101561145f578181101561145057604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610a92565b61145f848484840360006119c8565b50505050565b6001600160a01b03831661148f57604051634b637e8f60e11b815260006004820152602401610a92565b6001600160a01b0382166114b95760405163ec442f0560e01b815260006004820152602401610a92565b611202838383611be9565b6000546001600160a01b03163314610cc25760405163118cdaa760e01b8152336004820152602401610a92565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b60608060006115a3856020013561155c86611d13565b61156960a0890189612ab6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d3f92505050565b90935090506000816115b65760016115b9565b60025b90506115d96115cb6020880188612622565b826106fc60808a018a612ab6565b6004549093506001600160a01b0316801561165f5760405163043a78eb60e01b81526001600160a01b0382169063043a78eb9061161c9088908890600401612c52565b602060405180830381865afa158015611639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165d9190612c77565b505b5050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa96001600160a01b031663ddc28c586040518060a001604052808863ffffffff1681526020016116cc89611243565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611701929190612c94565b6040805180830381865afa15801561171d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117419190612d3e565b95945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611871576117cc8282815181106117bb576117bb612a7f565b6020026020010151604001516118a1565b8181815181106117de576117de612a7f565b6020026020010151604001516003600084848151811061180057611800612a7f565b60200260200101516000015163ffffffff1663ffffffff168152602001908152602001600020600084848151811061183a5761183a612a7f565b60200260200101516020015161ffff1661ffff16815260200190815260200160002090816118689190612da1565b5060010161179d565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610ca59190612e5f565b600281015161ffff8116600314610b435781604051639a6d49cd60e01b8152600401610a9291906121b1565b6118d561211a565b604080518082019091526000808252602082015260008061190c33604089013560608a013561190760208c018c612622565b611db9565b9150915060008061191d8984611546565b909250905061194961193260208b018b612622565b8383611943368d90038d018d612eef565b8b611ddf565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611997908d018d612622565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6001600160a01b0384166119f25760405163e602df0560e01b815260006004820152602401610a92565b6001600160a01b038316611a1c57604051634a1406b160e11b815260006004820152602401610a92565b6001600160a01b038085166000908152600660209081526040808320938716835292905220829055801561145f57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611a8f91815260200190565b60405180910390a350505050565b60007f00000000000000000000000000000000000000000000000000005af3107a4000611aca8184612f38565b6108b49190612f5a565b6000611ae360208284866129f0565b610b2a91612f71565b6000611afc6028602084866129f0565b611b0591612f8f565b60c01c9392505050565b60006108b47f00000000000000000000000000000000000000000000000000005af3107a40006001600160401b038416612f5a565b60006001600160a01b038416611b5a5761dead93505b611b648484611eea565b509092915050565b6060611b7b82602881866129f0565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b606084848484604051602001611bd09493929190612fc7565b6040516020818303038152906040529050949350505050565b6001600160a01b038316611c14578060076000828254611c099190613016565b90915550611c869050565b6001600160a01b03831660009081526005602052604090205481811015611c675760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610a92565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b038216611ca257600780548290039055611cc1565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611d0691815260200190565b60405180910390a3505050565b60006108b47f00000000000000000000000000000000000000000000000000005af3107a400083612f38565b8051606090151580611d88578484604051602001611d7492919091825260c01b6001600160c01b031916602082015260280190565b604051602081830303815290604052611daf565b84843385604051602001611d9f9493929190613029565b6040516020818303038152906040525b9150935093915050565b600080611dc7858585611207565b9092509050611dd68683611f20565b94509492505050565b611de761211a565b6000611df68460000151611f56565b602085015190915015611e1057611e108460200151611f7e565b7f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa96001600160a01b0316632637a450826040518060a001604052808b63ffffffff168152602001611e608c611243565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b8152600401611e9c929190612c94565b60806040518083038185885af1158015611eba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611edf919061306c565b979650505050505050565b6001600160a01b038216611f145760405163ec442f0560e01b815260006004820152602401610a92565b610b4360008383611be9565b6001600160a01b038216611f4a57604051634b637e8f60e11b815260006004820152602401610a92565b610b4382600083611be9565b6000813414611f7a576040516304fb820960e51b8152346004820152602401610a92565b5090565b60007f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa96001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200291906127da565b90506001600160a01b03811661202b576040516329b99a9560e11b815260040160405180910390fd5b6040805133602482018190527f0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa96001600160a01b0381811660448501526064808501889052855180860390910181526084909401909452602080840180516001600160e01b03166323b872dd60e01b1781528451610b4396881695899361145f93889360009283929091839182885af1806120cc576040513d6000823e3d81fd5b50506000513d915081156120e45780600114156120f1565b6001600160a01b0384163b155b1561145f57604051635274afe760e01b81526001600160a01b0385166004820152602401610a92565b60405180606001604052806000801916815260200160006001600160401b0316815260200161215c604051806040016040528060008152602001600081525090565b905290565b60005b8381101561217c578181015183820152602001612164565b50506000910152565b6000815180845261219d816020860160208601612161565b601f01601f19169290920160200192915050565b602081526000610b2a6020830184612185565b6001600160a01b03811681146111bc57600080fd5b600080604083850312156121ec57600080fd5b82356121f7816121c4565b946020939093013593505050565b600060e0828403121561221757600080fd5b50919050565b60006020828403121561222f57600080fd5b81356001600160401b0381111561224557600080fd5b610cd184828501612205565b8351815260208085015190820152600060a0820160a0604084015280855180835260c08501915060c08160051b86010192506020870160005b828110156122d25760bf1987860301845281518051865260208101519050604060208701526122bc6040870182612185565b955050602093840193919091019060010161228a565b5050855160608601525050602084015160808401529050610cd1565b60006060828403121561221757600080fd5b60008083601f84011261231257600080fd5b5081356001600160401b0381111561232957600080fd5b60208301915083602082850101111561234157600080fd5b9250929050565b600080600080600080600060e0888a03121561236357600080fd5b61236d89896122ee565b96506060880135955060808801356001600160401b0381111561238f57600080fd5b61239b8a828b01612300565b90965094505060a08801356123af816121c4565b925060c08801356001600160401b038111156123ca57600080fd5b6123d68a828b01612300565b989b979a50959850939692959293505050565b6000806000606084860312156123fe57600080fd5b8335612409816121c4565b92506020840135612419816121c4565b929592945050506040919091013590565b803563ffffffff8116811461243e57600080fd5b919050565b6000806040838503121561245657600080fd5b6121f78361242a565b80151581146111bc57600080fd5b6000806040838503121561248057600080fd5b82356001600160401b0381111561249657600080fd5b6124a285828601612205565b92505060208301356124b38161245f565b809150509250929050565b8151815260208083015190820152604081016108b4565b803561ffff8116811461243e57600080fd5b600080604083850312156124fa57600080fd5b6125038361242a565b9150612511602084016124d5565b90509250929050565b60006020828403121561252c57600080fd5b8135610b2a816121c4565b60008060008060a0858703121561254d57600080fd5b61255786866122ee565b935060608501356001600160401b0381111561257257600080fd5b61257e87828801612300565b9094509250506080850135612592816121c4565b939692955090935050565b60008083601f8401126125af57600080fd5b5081356001600160401b038111156125c657600080fd5b6020830191508360208260051b850101111561234157600080fd5b600080602083850312156125f457600080fd5b82356001600160401b0381111561260a57600080fd5b6126168582860161259d565b90969095509350505050565b60006020828403121561263457600080fd5b610b2a8261242a565b6000806000806060858703121561265357600080fd5b61265c8561242a565b935061266a602086016124d5565b925060408501356001600160401b0381111561268557600080fd5b61269187828801612300565b95989497509550505050565b600080600083850360808112156126b357600080fd5b84356001600160401b038111156126c957600080fd5b6126d587828801612205565b9450506040601f19820112156126ea57600080fd5b5060208401915060608401356126ff816121c4565b809150509250925092565b600060c082019050835182526001600160401b0360208501511660208301526040840151612745604084018280518252602090810151910152565b5082516080830152602083015160a0830152610b2a565b6000806040838503121561276f57600080fd5b823561277a816121c4565b915060208301356124b3816121c4565b60006060828403121561279c57600080fd5b610b2a83836122ee565b600181811c908216806127ba57607f821691505b60208210810361221757634e487b7160e01b600052602260045260246000fd5b6000602082840312156127ec57600080fd5b8151610b2a816121c4565b60006020828403121561280957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561284857612848612810565b60405290565b604080519081016001600160401b038111828210171561284857612848612810565b604051601f8201601f191681016001600160401b038111828210171561289857612898612810565b604052919050565b60006001600160401b038211156128b9576128b9612810565b50601f01601f191660200190565b60006001600160401b038311156128e0576128e0612810565b8260051b6128f060208201612870565b8481529083019060208101903683111561290957600080fd5b845b838110156129e65780356001600160401b0381111561292957600080fd5b8601606036829003121561293c57600080fd5b612944612826565b61294d8261242a565b815261295b602083016124d5565b602082015260408201356001600160401b0381111561297957600080fd5b919091019036601f83011261298d57600080fd5b81356129a061299b826128a0565b612870565b8181523660208386010111156129b557600080fd5b816020850160208301376000602083830101528060408401525050808552505060208301925060208101905061290b565b5095945050505050565b60008085851115612a0057600080fd5b83861115612a0d57600080fd5b5050820193919092039150565b60008451612a2c818460208901612161565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610cd1602083018486612a42565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112612aac57600080fd5b9190910192915050565b6000808335601e19843603018112612acd57600080fd5b8301803591506001600160401b03821115612ae757600080fd5b60200191503681900382131561234157600080fd5b6001600160401b03811681146111bc57600080fd5b63ffffffff612b1f8961242a565b1681526020888101359082015260006040890135612b3c81612afc565b6001600160401b03811660408401525087606083015260e06080830152612b6760e083018789612a42565b6001600160a01b03861660a084015282810360c0840152612b89818587612a42565b9a9950505050505050505050565b600060208284031215612ba957600080fd5b81516001600160401b03811115612bbf57600080fd5b8201601f81018413612bd057600080fd5b8051612bde61299b826128a0565b818152856020838501011115612bf357600080fd5b611741826020830160208601612161565b600060208284031215612c1657600080fd5b8135610b2a81612afc565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610ba46080830184612185565b604081526000612c656040830185612185565b82810360208401526117418185612185565b600060208284031215612c8957600080fd5b8151610b2a8161245f565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a06080840152612cca60e0840182612185565b90506060850151603f198483030160a0850152612ce78282612185565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b600060408284031215612d1f57600080fd5b612d2761284e565b825181526020928301519281019290925250919050565b600060408284031215612d5057600080fd5b610b2a8383612d0d565b601f82111561120257806000526020600020601f840160051c81016020851015612d815750805b601f840160051c820191505b818110156110f55760008155600101612d8d565b81516001600160401b03811115612dba57612dba612810565b612dce81612dc884546127a6565b84612d5a565b6020601f821160018114612e025760008315612dea5750848201515b600019600385901b1c1916600184901b1784556110f5565b600084815260208120601f198516915b82811015612e325787850151825560209485019460019092019101612e12565b5084821015612e505786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b82811015612ee357603f19878603018452815163ffffffff815116865261ffff60208201511660208701526040810151905060606040870152612ecd6060870182612185565b9550506020938401939190910190600101612e87565b50929695505050505050565b60006040828403128015612f0257600080fd5b50612f0b61284e565b823581526020928301359281019290925250919050565b634e487b7160e01b600052601160045260246000fd5b600082612f5557634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176108b4576108b4612f22565b803560208310156108b457600019602084900360031b1b1692915050565b80356001600160c01b03198116906008841015612fc0576001600160c01b0319600885900360031b81901b82161691505b5092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161300681602c850160208701612161565b91909101602c0195945050505050565b808201808211156108b4576108b4612f22565b8481526001600160401b0360c01b8460c01b1660208201528260288201526000825161305c816048850160208701612161565b9190910160480195945050505050565b6000608082840312801561307f57600080fd5b50613088612826565b82518152602083015161309a81612afc565b60208201526130ac8460408501612d0d565b6040820152939250505056fea264697066735822122068198981facd40d56e4088c3bf4271ce2ed08ed24f71105748e8464517e41ecc64736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa9000000000000000000000000ff2ddef995bf1de2df67612bda5f9901798580a2000000000000000000000000000000000000000000000000000000000000000452656b7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000452454b5400000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Rekt
Arg [1] : _symbol (string): REKT
Arg [2] : _lzEndpoint (address): 0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9
Arg [3] : _delegate (address): 0xfF2DdEF995bF1dE2df67612BDa5f9901798580a2
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000003a73033c0b1407574c76bdbac67f126f6b4a9aa9
Arg [3] : 000000000000000000000000ff2ddef995bf1de2df67612bda5f9901798580a2
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [5] : 52656b7400000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [7] : 52454b5400000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
206:950:40:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89:34;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3979:186;;;;;;;;;;-1:-1:-1;3979:186:34;;;;;:::i;:::-;;:::i;:::-;;;1443:14:42;;1436:22;1418:41;;1406:2;1391:18;3979:186:34;1278:187:42;5176:1276:25;;;;;;;;;;-1:-1:-1;5176:1276:25;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;2330:27::-;;;;;;;;;;-1:-1:-1;2330:27:25;;;;-1:-1:-1;;;;;2330:27:25;;;;;;-1:-1:-1;;;;;3621:32:42;;;3603:51;;3591:2;3576:18;2330:27:25;3457:203:42;4368:708:12;;;;;;:::i;:::-;;:::i;:::-;;2204:40:25;;;;;;;;;;;;2243:1;2204:40;;;;;5448:6:42;5436:19;;;5418:38;;5406:2;5391:18;2204:40:25;5274:188:42;3475:140:25;;;;;;;;;;-1:-1:-1;3475:140:25;;;-1:-1:-1;;;5637:52:42;;3606:1:25;5720:2:42;5705:18;;5698:59;5610:18;3475:140:25;5467:296:42;1287:235:10;;;;;;;;;;-1:-1:-1;1287:235:10;;;843:1:13;5938:50:42;;678:1:12;6019:2:42;6004:18;;5997:59;5911:18;1287:235:10;5768:294:42;2830:97:34;;;;;;;;;;-1:-1:-1;2908:12:34;;2830:97;;;6213:25:42;;;6201:2;6186:18;2830:97:34;6067:177:42;2167:31:25;;;;;;;;;;;;2197:1;2167:31;;4757:244:34;;;;;;;;;;-1:-1:-1;4757:244:34;;;;;:::i;:::-;;:::i;2688:82::-;;;;;;;;;;-1:-1:-1;2761:2:34;2688:82;;;6934:4:42;6922:17;;;6904:36;;6892:2;6877:18;2688:82:34;6762:184:42;1724:108:11;;;;;;;;;;-1:-1:-1;1724:108:11;;;;;:::i;:::-;;:::i;6903:774:25:-;;;;;;;;;;-1:-1:-1;6903:774:25;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;875:93:19:-;;;;;;;;;;-1:-1:-1;956:4:19;875:93;;538::18;;;;;;;;;;-1:-1:-1;538:93:18;;;;;:::i;:::-;;:::i;16151:132:25:-;;;;;;;;;;-1:-1:-1;16151:132:25;;;;;:::i;:::-;16256:11;;;;;16233:4;16256:11;;;:5;:11;;;;;;:20;;16151:132;446:46:11;;;;;;;;;;;;;;;4657:163:25;;;;;;;;;;-1:-1:-1;4657:163:25;;;;;:::i;:::-;;:::i;2985:116:34:-;;;;;;;;;;-1:-1:-1;2985:116:34;;;;;:::i;:::-;-1:-1:-1;;;;;3076:18:34;3050:7;3076:18;;;:9;:18;;;;;;;2985:116;2293:101:29;;;;;;;;;;;;;:::i;3507:128:12:-;;;;;;;;;;-1:-1:-1;3507:128:12;;;;;:::i;:::-;3596:12;3507:128;;;;;;;;-1:-1:-1;;;;;9595:31:42;;;9577:50;;9565:2;9550:18;3507:128:12;9433:200:42;2013:216:12;;;;;;;;;;-1:-1:-1;2013:216:12;;;;;:::i;:::-;;:::i;1063:90:40:-;;;;;;;;;;-1:-1:-1;1144:1:40;1063:90;;1638:85:29;;;;;;;;;;-1:-1:-1;1684:7:29;1710:6;-1:-1:-1;;;;;1710:6:29;1638:85;;1962:93:34;;;;;;;;;;;;;:::i;1861:46:25:-;;;;;;;;;;;;;;;1460:94:23;;;;;;;;;;-1:-1:-1;1519:4:23;1460:94;;3296:178:34;;;;;;;;;;-1:-1:-1;3296:178:34;;;;;:::i;:::-;;:::i;559:23:19:-;;;;;;;;;;-1:-1:-1;559:23:19;;;;-1:-1:-1;;;;;559:23:19;;;1391:156:18;;;;;;;;;;-1:-1:-1;1391:156:18;;;;;:::i;:::-;;:::i;569:48:11:-;;;;;;;;;;-1:-1:-1;569:48:11;;;;;:::i;:::-;;;;;;;;;;;;;;3510:981:18;;;;;;;;;;-1:-1:-1;3510:981:18;;;;;:::i;:::-;;:::i;1698:1333:19:-;;;;;;:::i;:::-;;:::i;8365:290:25:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;3252:105:11:-;;;;;;;;;;-1:-1:-1;3252:105:11;;;;;:::i;:::-;;:::i;3679:409:19:-;;;;;;:::i;:::-;;:::i;1100:139::-;;;;;;;;;;-1:-1:-1;1100:139:19;;;;;:::i;:::-;;:::i;3532:140:34:-;;;;;;;;;;-1:-1:-1;3532:140:34;;;;;:::i;:::-;-1:-1:-1;;;;;3638:18:34;;;3612:7;3638:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3532:140;2543:215:29;;;;;;;;;;-1:-1:-1;2543:215:29;;;;;:::i;:::-;;:::i;2771:149:12:-;;;;;;;;;;-1:-1:-1;2771:149:12;;;;;:::i;:::-;;:::i;1760:89:34:-;1805:13;1837:5;1830:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89;:::o;3979:186::-;4052:4;735:10:38;4106:31:34;735:10:38;4122:7:34;4131:5;4106:8;:31::i;:::-;4154:4;4147:11;;;3979:186;;;;;:::o;5176:1276:25:-;-1:-1:-1;;;;;;;;;;;;;;;;;5328:35:25;5365:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;5365:28:25;5409:19;5483;5512:4;-1:-1:-1;;;;;5512:10:25;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5505:32:25;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5601;;;;;;;;;;;;;;;;;;5752:21;;-1:-1:-1;5752:21:25;;;;;;;;;5601:34;;-1:-1:-1;5601:34:25;;-1:-1:-1;5752:21:25;;;;-1:-1:-1;;;;;;;;;;;;;;;;;5752:21:25;;;;;;;;;;;;;;;-1:-1:-1;5736:37:25;-1:-1:-1;6210:20:25;;6260:120;6284:19;;;;6317:22;;;;6353:17;;;;6284:10;6353:17;:::i;:::-;6260:10;:120::i;:::-;6403:42;;;;;;;;;;;;;;;;5176:1276;;;;-1:-1:-1;;;;;;5176:1276:25:o;4368:708:12:-;4681:8;-1:-1:-1;;;;;4673:31:12;4694:10;4673:31;4669:68;;4713:24;;-1:-1:-1;;;4713:24:12;;4726:10;4713:24;;;3603:51:42;3576:18;;4713:24:12;;;;;;;;4669:68;4873:14;;;;;;4837:32;;4854:14;;4873:7;4854:14;:::i;:::-;4837:16;:32::i;:::-;:50;4833:103;;4905:14;;;;:7;:14;:::i;:::-;4896:40;;-1:-1:-1;;;4896:40:12;;15768:10:42;15756:23;;;4896:40:12;;;15738:42:42;4921:14:12;;;;15796:18:42;;;15789:34;15711:18;;4896:40:12;15566:263:42;4833:103:12;5010:59;5021:7;5030:5;5037:8;;5047:9;5058:10;;5010;:59::i;:::-;4368:708;;;;;;;:::o;4757:244:34:-;4844:4;735:10:38;4900:37:34;4916:4;735:10:38;4931:5:34;4900:15;:37::i;:::-;4947:26;4957:4;4963:2;4967:5;4947:9;:26::i;:::-;4990:4;4983:11;;;4757:244;;;;;;:::o;1724:108:11:-;1531:13:29;:11;:13::i;:::-;1804:21:11::1;1813:4;1819:5;1804:8;:21::i;:::-;1724:108:::0;;:::o;6903:774:25:-;-1:-1:-1;;;;;;;;;;;;;;;;;7237:24:25;7265:74;7276:19;;;;7297:22;;;;7321:17;;;;7276:10;7321:17;:::i;7265:74::-;7234:105;;;7428:20;7450;7474:49;7494:10;7506:16;7474:19;:49::i;:::-;7427:96;;-1:-1:-1;7427:96:25;-1:-1:-1;7612:58:25;7619:17;;;;:10;:17;:::i;:::-;7638:7;7647;7656:13;7612:6;:58::i;:::-;7605:65;6903:774;-1:-1:-1;;;;;;6903:774:25:o;538:93:18:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;4657:163:25:-;1531:13:29;:11;:13::i;:::-;4740:12:25::1;:28:::0;;-1:-1:-1;;;;;;4740:28:25::1;-1:-1:-1::0;;;;;4740:28:25;::::1;::::0;;::::1;::::0;;;4783:30:::1;::::0;3603:51:42;;;4783:30:25::1;::::0;3591:2:42;3576:18;4783:30:25::1;;;;;;;;4657:163:::0;:::o;2293:101:29:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;2013:216:12:-;-1:-1:-1;;;;;2198:24:12;;2217:4;2198:24;2013:216;;;;;;;:::o;1962:93:34:-;2009:13;2041:7;2034:14;;;;;:::i;3296:178::-;3365:4;735:10:38;3419:27:34;735:10:38;3436:2:34;3440:5;3419:9;:27::i;1391:156:18:-;1531:13:29;:11;:13::i;:::-;1503:37:18::1;;1523:16:::0;;1503:37:::1;:::i;:::-;:19;:37::i;3510:981::-:0;3701:21;;;3677;3701;;;:15;:21;;;;;;;;:31;;;;;;;;;;3677:55;;3653:12;;3677:21;3701:31;3677:55;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:8;:15;3880:1;3861:20;3857:46;;3890:13;;3883:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3883:20:18;;-1:-1:-1;3883:20:18;;-1:-1:-1;;;;3883:20:18;3857:46;3988:1;3964:25;;;3960:46;;3998:8;-1:-1:-1;3991:15:18;;3960:46;4153:1;4129:25;;4125:267;;4170:34;4190:13;;4170:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4170:19:18;;-1:-1:-1;;;4170:34:18:i;:::-;4353:8;4363:17;:13;4377:1;4363:13;;:17;:::i;:::-;4340:41;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4333:48;;;;;4125:267;4470:13;;4455:29;;-1:-1:-1;;;4455:29:18;;;;;;;;;:::i;1698:1333:19:-;1799:9;1794:1037;1814:19;;;1794:1037;;;1854:29;1886:8;;1895:1;1886:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;1854:43;-1:-1:-1;1980:50:19;1987:20;;;;1854:43;1987:20;:::i;:::-;2009;;;;16256:11:25;;;;;16233:4;16256:11;;;:5;:11;;;;;;:20;;16151:132;1980:50:19;1975:65;;2032:8;;;1975:65;2602:4;:22;2633:12;;;;:6;2696:11;;;;2725:14;;;;2633:6;2725:14;:::i;:::-;2757:15;;;;;;;;:::i;:::-;2790:16;;;;:6;:16;:::i;:::-;2602:218;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1840:991;1794:1037;1835:3;;1794:1037;;;;2988:10;-1:-1:-1;;;;;2978:43:19;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2978:45:19;;;;;;;;;;;;:::i;:::-;2961:63;;-1:-1:-1;;;2961:63:19;;;;;;;;:::i;8365:290:25:-;8526:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;8609:39:25;8615:10;8627:4;8633:14;8609:5;:39::i;:::-;8602:46;;;;8365:290;;;;;;;:::o;3252:105:11:-;1531:13:29;:11;:13::i;:::-;3319:31:11::1;::::0;-1:-1:-1;;;3319:31:11;;-1:-1:-1;;;;;3621:32:42;;;3319:31:11::1;::::0;::::1;3603:51:42::0;3319:8:11::1;:20;::::0;::::1;::::0;3576:18:42;;3319:31:11::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3252:105:::0;:::o;3679:409:19:-;3958:10;3980:4;3958:27;3954:50;;3994:10;;-1:-1:-1;;;3994:10:19;;;;;;;;;;;3954:50;4014:67;4033:7;4042:5;4049:8;;4059:9;4070:10;;4014:18;:67::i;1100:139::-;1531:13:29;:11;:13::i;:::-;1175:8:19::1;:20:::0;;-1:-1:-1;;;;;;1175:20:19::1;-1:-1:-1::0;;;;;1175:20:19;::::1;::::0;;::::1;::::0;;;1210:22:::1;::::0;3603:51:42;;;1210:22:19::1;::::0;3591:2:42;3576:18;1210:22:19::1;3457:203:42::0;2543:215:29;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:29;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:29;;2700:1:::1;2672:31;::::0;::::1;3603:51:42::0;3576:18;;2672:31:29::1;3457:203:42::0;2623:91:29::1;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;2771:149:12:-;2853:4;2900:13;;;;;;2876:5;;2853:4;;2882:13;;2900:6;2882:13;:::i;:::-;2876:20;;;;;;;;;;;;;-1:-1:-1;2876:20:12;;:37;;2771:149;-1:-1:-1;;2771:149:12:o;8707:128:34:-;8791:37;8800:5;8807:7;8816:5;8823:4;8791:8;:37::i;:::-;8707:128;;;:::o;18168:668:25:-;18310:20;18332:24;18506:22;18518:9;18506:11;:22::i;:::-;18491:37;;18654:12;18635:31;;18736:12;18717:16;:31;18713:117;;;18771:48;;-1:-1:-1;;;18771:48:25;;;;;22970:25:42;;;23011:18;;;23004:34;;;22943:18;;18771:48:25;22796:248:42;2718:196:11;2822:11;;;2788:7;2822:11;;;:5;:11;;;;;;;2843:43;;2874:12;;-1:-1:-1;;;2874:12:11;;23223:10:42;23211:23;;2874:12:11;;;23193:42:42;23166:18;;2874:12:11;23049:192:42;12944:1806:25;13421:17;13441:36;:17;:8;;:15;:17::i;:::-;2891:2:28;2780:123;13441:36:25;13421:56;;13610:24;13637:62;13645:9;13656:26;13662:19;:8;;:17;:19::i;:::-;13656:5;:26::i;:::-;13684:14;;;;:7;:14;:::i;:::-;13637:7;:62::i;:::-;13610:89;-1:-1:-1;243:2:28;-1:-1:-1;;13710:955:25;;;13814:23;13840:175;13883:13;;;;;;;;:::i;:::-;13914:14;;;;:7;:14;:::i;:::-;13946:16;13980:21;:8;;:19;:21::i;:::-;13840:25;:175::i;:::-;14562:92;;-1:-1:-1;;;14562:92:25;;13814:201;;-1:-1:-1;;;;;;14562:8:25;:20;;;;:92;;14583:9;;14594:5;;14601:1;;13814:201;;14562:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13737:928;13710:955;-1:-1:-1;;;;;14680:63:25;;14692:5;14680:63;14699:14;;;;:7;:14;:::i;:::-;14680:63;;;15768:10:42;15756:23;;;15738:42;;15811:2;15796:18;;15789:34;;;15711:18;14680:63:25;;;;;;;13247:1503;;12944:1806;;;;;;;:::o;10396:476:34:-;-1:-1:-1;;;;;3638:18:34;;;10495:24;3638:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;10561:36:34;;10557:309;;;10636:5;10617:16;:24;10613:130;;;10668:60;;-1:-1:-1;;;10668:60:34;;-1:-1:-1;;;;;24468:32:42;;10668:60:34;;;24450:51:42;24517:18;;;24510:34;;;24560:18;;;24553:34;;;24423:18;;10668:60:34;24248:345:42;10613:130:34;10784:57;10793:5;10800:7;10828:5;10809:16;:24;10835:5;10784:8;:57::i;:::-;10485:387;10396:476;;;:::o;5374:300::-;-1:-1:-1;;;;;5457:18:34;;5453:86;;5498:30;;-1:-1:-1;;;5498:30:34;;5525:1;5498:30;;;3603:51:42;3576:18;;5498:30:34;3457:203:42;5453:86:34;-1:-1:-1;;;;;5552:16:34;;5548:86;;5591:32;;-1:-1:-1;;;5591:32:34;;5620:1;5591:32;;;3603:51:42;3576:18;;5591:32:34;3457:203:42;5548:86:34;5643:24;5651:4;5657:2;5661:5;5643:7;:24::i;1796:162:29:-;1684:7;1710:6;-1:-1:-1;;;;;1710:6:29;735:10:38;1855:23:29;1851:101;;1901:40;;-1:-1:-1;;;1901:40:29;;735:10:38;1901:40:29;;;3603:51:42;3576:18;;1901:40:29;3457:203:42;2286:134:11;2359:11;;;;;;;:5;:11;;;;;;;;;:19;;;2393:20;;15738:42:42;;;15796:18;;15789:34;;;2393:20:11;;15711:18:42;2393:20:11;;;;;;;2286:134;;:::o;10990:1436:25:-;11122:20;11144;11176:15;11347:324;11379:10;:13;;;11406:16;11412:9;11406:5;:16::i;:::-;11640:21;;;;:10;:21;:::i;:::-;11347:324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11347:18:25;;-1:-1:-1;;;11347:324:25:i;:::-;11323:348;;-1:-1:-1;11323:348:25;-1:-1:-1;11751:14:25;11323:348;11768:33;;2197:1;11768:33;;;2243:1;11768:33;11751:50;-1:-1:-1;11923:67:25;11938:17;;;;:10;:17;:::i;:::-;11957:7;11966:23;;;;:10;:23;:::i;11923:67::-;12248:12;;11913:77;;-1:-1:-1;;;;;;12248:12:25;12340:23;;12336:83;;12365:54;;-1:-1:-1;;;12365:54:25;;-1:-1:-1;;;;;12365:36:25;;;;;:54;;12402:7;;12411;;12365:54;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;12336:83;11166:1260;;;10990:1436;;;;;:::o;2038:391:13:-;-1:-1:-1;;;;;;;;;;;;;;;;;2259:8:13;-1:-1:-1;;;;;2259:14:13;;2291:86;;;;;;;;2307:7;2291:86;;;;;;2316:25;2333:7;2316:16;:25::i;:::-;2291:86;;;;2343:8;2291:86;;;;2353:8;2291:86;;;;2363:13;2291:86;;;;;2403:4;2259:163;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2240:182;2038:391;-1:-1:-1;;;;;2038:391:13:o;2912:187:29:-;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:29;;;-1:-1:-1;;;;;;3020:17:29;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;2237:514:18:-;2345:9;2340:354;2364:16;:23;2360:1;:27;2340:354;;;2522:48;2542:16;2559:1;2542:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2522:19;:48::i;:::-;2656:16;2673:1;2656:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:15;:40;2600:16;2617:1;2600:19;;;;;;;;:::i;:::-;;;;;;;:23;;;2584:40;;;;;;;;;;;;;;;:69;2625:16;2642:1;2625:19;;;;;;;;:::i;:::-;;;;;;;:27;;;2584:69;;;;;;;;;;;;;;;:99;;;;;;:::i;:::-;-1:-1:-1;2389:3:18;;2340:354;;;;2709:35;2727:16;2709:35;;;;;;:::i;4631:264::-;4801:1;4787:16;;4781:23;4827:28;;;463:1;4827:28;4823:65;;4879:8;4864:24;;-1:-1:-1;;;4864:24:18;;;;;;;;:::i;9363:1333:25:-;9517:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;9915:20:25;;9965:140;9985:10;10009:19;;;;10042:22;;;;10078:17;;;;10009:10;10078:17;:::i;:::-;9965:6;:140::i;:::-;9914:191;;;;10194:20;10216;10240:49;10260:10;10272:16;10240:19;:49::i;:::-;10193:96;;-1:-1:-1;10193:96:25;-1:-1:-1;10412:66:25;10420:17;;;;:10;:17;:::i;:::-;10439:7;10448;10412:66;;;;;;;10457:4;10412:66;:::i;:::-;10463:14;10412:7;:66::i;:::-;10544:42;;;;;;;;;;;;;;;;;;;10610:15;;10399:79;;-1:-1:-1;10544:42:25;;-1:-1:-1;10646:10:25;;10610:15;10602:87;;10627:17;;;;:10;:17;:::i;:::-;10602:87;;;30723:10:42;30711:23;;;30693:42;;30766:2;30751:18;;30744:34;;;30794:18;;30787:34;;;30681:2;30666:18;10602:87:25;;;;;;;9583:1113;;;;9363:1333;;;;;;:::o;9682:432:34:-;-1:-1:-1;;;;;9794:19:34;;9790:89;;9836:32;;-1:-1:-1;;;9836:32:34;;9865:1;9836:32;;;3603:51:42;3576:18;;9836:32:34;3457:203:42;9790:89:34;-1:-1:-1;;;;;9892:21:34;;9888:90;;9936:31;;-1:-1:-1;;;9936:31:34;;9964:1;9936:31;;;3603:51:42;3576:18;;9936:31:34;3457:203:42;9888:90:34;-1:-1:-1;;;;;9987:18:34;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;10032:76;;;;10082:7;-1:-1:-1;;;;;10066:31:34;10075:5;-1:-1:-1;;;;;10066:31:34;;10091:5;10066:31;;;;6213:25:42;;6201:2;6186:18;;6067:177;10066:31:34;;;;;;;;9682:432;;;;:::o;16677:172:25:-;16748:16;16821:21;16784:33;16821:21;16784:9;:33;:::i;:::-;16783:59;;;;:::i;1573:123:28:-;1633:7;1667:21;188:2;1633:7;1667:4;;:21;:::i;:::-;1659:30;;;:::i;1874:152::-;1936:6;1975:42;243:2;188;1975:4;;:42;:::i;:::-;1968:50;;;:::i;:::-;1961:58;;;1874:152;-1:-1:-1;;;1874:152:28:o;17073:139:25:-;17137:16;17172:33;17184:21;-1:-1:-1;;;;;17172:33:25;;;:::i;2939:462:23:-;3073:24;-1:-1:-1;;;;;3113:19:23;;3109:46;;3148:6;3134:21;;3109:46;3251:21;3257:3;3262:9;3251:5;:21::i;:::-;-1:-1:-1;3385:9:23;;2939:462;-1:-1:-1;;2939:462:23:o;2186:130:28:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:28;;2186:130;-1:-1:-1;;;;;;2186:130:28:o;640:284:27:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;5989:1107:34:-;-1:-1:-1;;;;;6078:18:34;;6074:540;;6230:5;6214:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;6074:540:34;;-1:-1:-1;6074:540:34;;-1:-1:-1;;;;;6288:15:34;;6266:19;6288:15;;;:9;:15;;;;;;6321:19;;;6317:115;;;6367:50;;-1:-1:-1;;;6367:50:34;;-1:-1:-1;;;;;24468:32:42;;6367:50:34;;;24450:51:42;24517:18;;;24510:34;;;24560:18;;;24553:34;;;24423:18;;6367:50:34;24248:345:42;6317:115:34;-1:-1:-1;;;;;6552:15:34;;;;;;:9;:15;;;;;6570:19;;;;6552:37;;6074:540;-1:-1:-1;;;;;6628:16:34;;6624:425;;6791:12;:21;;;;;;;6624:425;;;-1:-1:-1;;;;;7002:13:34;;;;;;:9;:13;;;;;:22;;;;;;6624:425;7079:2;-1:-1:-1;;;;;7064:25:34;7073:4;-1:-1:-1;;;;;7064:25:34;;7083:5;7064:25;;;;6213::42;;6201:2;6186:18;;6067:177;7064:25:34;;;;;;;;5989:1107;;;:::o;17436:147:25:-;17501:15;17542:33;17554:21;17542:9;:33;:::i;598:506:28:-;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;32844:19:42;;;32919:3;32897:16;-1:-1:-1;;;;;;32893:51:42;32888:2;32879:12;;32872:73;32970:2;32961:12;;32689:290;1057:40:28;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;2037:567:23:-;2198:20;2220:24;2291:44;2302:9;2313:12;2327:7;2291:10;:44::i;:::-;2256:79;;-1:-1:-1;2256:79:23;-1:-1:-1;2571:26:23;2577:5;2256:79;2571:5;:26::i;:::-;2037:567;;;;;;;:::o;3188:766:13:-;3389:31;;:::i;:::-;3554:20;3577:26;3588:4;:14;;;3577:10;:26::i;:::-;3617:15;;;;3554:49;;-1:-1:-1;3617:19:13;3613:53;;3638:28;3650:4;:15;;;3638:11;:28::i;:::-;3755:8;-1:-1:-1;;;;;3755:13:13;;3777:12;3809:92;;;;;;;;3825:7;3809:92;;;;;;3834:25;3851:7;3834:16;:25::i;:::-;3809:92;;;;3861:8;3809:92;;;;3871:8;3809:92;;;;3899:1;3881:4;:15;;;:19;3809:92;;;;;3919:14;3755:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3677:270;3188:766;-1:-1:-1;;;;;;;3188:766:13:o;7439:208:34:-;-1:-1:-1;;;;;7509:21:34;;7505:91;;7553:32;;-1:-1:-1;;;7553:32:34;;7582:1;7553:32;;;3603:51:42;3576:18;;7553:32:34;3457:203:42;7505:91:34;7605:35;7621:1;7625:7;7634:5;7605:7;:35::i;7965:206::-;-1:-1:-1;;;;;8035:21:34;;8031:89;;8079:30;;-1:-1:-1;;;8079:30:34;;8106:1;8079:30;;;3603:51:42;3576:18;;8079:30:34;3457:203:42;8031:89:34;8129:35;8137:7;8154:1;8158:5;8129:7;:35::i;4650:191:13:-;4716:17;4762:10;4749:9;:23;4745:62;;4781:26;;-1:-1:-1;;;4781:26:13;;4797:9;4781:26;;;6213:25:42;6186:18;;4781:26:13;6067:177:42;4745:62:13;-1:-1:-1;4824:10:13;4650:191::o;5218:410::-;5371:15;5389:8;-1:-1:-1;;;;;5389:16:13;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5371:36;-1:-1:-1;;;;;;5421:21:13;;5417:54;;5451:20;;-1:-1:-1;;;5451:20:13;;;;;;;;;;;5417:54;1745:53:37;;;5578:10:13;1745:53:37;;;34288:51:42;;;5598:8:13;-1:-1:-1;;;;;34375:32:42;;;34355:18;;;34348:60;34424:18;;;;34417:34;;;1745:53:37;;;;;;;;;;34261:18:42;;;;1745:53:37;;;;;;;;;-1:-1:-1;;;;;1745:53:37;-1:-1:-1;;;1745:53:37;;;8600:11;;5545:76:13;;:32;;;5609:11;;1718:81:37;;5545:32:13;;-1:-1:-1;;;;1745:53:37;;-1:-1:-1;;;5545:32:13;8566:5:37;8561:60;8673:7;8663:176;;8717:4;8711:11;8762:16;8759:1;8754:3;8739:40;8808:16;8803:3;8796:29;8663:176;-1:-1:-1;;8916:1:37;8910:8;8866:16;;-1:-1:-1;8942:15:37;;:68;;8994:11;9009:1;8994:16;;8942:68;;;-1:-1:-1;;;;;8960:26:37;;;:31;8942:68;8938:146;;;9033:40;;-1:-1:-1;;;9033:40:37;;-1:-1:-1;;;;;3621:32:42;;9033:40:37;;;3603:51:42;3576:18;;9033:40:37;3457:203:42;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:42:-;99:1;109:113;123:6;120:1;117:13;109:113;;;199:11;;;193:18;180:11;;;173:39;145:2;138:10;109:113;;;-1:-1:-1;;256:1:42;238:16;;231:27;14:250::o;269:271::-;311:3;349:5;343:12;376:6;371:3;364:19;392:76;461:6;454:4;449:3;445:14;438:4;431:5;427:16;392:76;:::i;:::-;522:2;501:15;-1:-1:-1;;497:29:42;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:42:o;545:220::-;694:2;683:9;676:21;657:4;714:45;755:2;744:9;740:18;732:6;714:45;:::i;770:131::-;-1:-1:-1;;;;;845:31:42;;835:42;;825:70;;891:1;888;881:12;906:367;974:6;982;1035:2;1023:9;1014:7;1010:23;1006:32;1003:52;;;1051:1;1048;1041:12;1003:52;1090:9;1077:23;1109:31;1134:5;1109:31;:::i;:::-;1159:5;1237:2;1222:18;;;;1209:32;;-1:-1:-1;;;906:367:42:o;1470:158::-;1532:5;1577:3;1568:6;1563:3;1559:16;1555:26;1552:46;;;1594:1;1591;1584:12;1552:46;-1:-1:-1;1616:6:42;1470:158;-1:-1:-1;1470:158:42:o;1633:360::-;1721:6;1774:2;1762:9;1753:7;1749:23;1745:32;1742:52;;;1790:1;1787;1780:12;1742:52;1830:9;1817:23;-1:-1:-1;;;;;1855:6:42;1852:30;1849:50;;;1895:1;1892;1885:12;1849:50;1918:69;1979:7;1970:6;1959:9;1955:22;1918:69;:::i;2152:1300::-;2072:12;;2060:25;;2134:4;2123:16;;;2117:23;2101:14;;;2094:47;2518:4;2566:3;2551:19;;2660:3;2655:2;2644:9;2640:18;2633:31;2684:6;2719;2713:13;2750:6;2742;2735:22;2788:3;2777:9;2773:19;2766:26;;2851:3;2841:6;2838:1;2834:14;2823:9;2819:30;2815:40;2801:54;;2890:4;2882:6;2878:17;2913:1;2923:437;2937:6;2934:1;2931:13;2923:437;;;3030:3;3026:8;3014:9;3006:6;3002:22;2998:37;2993:3;2986:50;3065:6;3059:13;3106:2;3100:9;3092:6;3085:25;3157:4;3153:2;3149:13;3143:20;3123:40;;3202:2;3195:4;3187:6;3183:17;3176:29;3228:48;3272:2;3264:6;3260:15;3246:12;3228:48;:::i;:::-;3218:58;-1:-1:-1;;3311:4:42;3336:14;;;;3299:17;;;;;2959:1;2952:9;2923:437;;;-1:-1:-1;;2072:12:42;;3442:2;3427:18;;2060:25;-1:-1:-1;;2134:4:42;2123:16;;2117:23;2101:14;;;2094:47;3377:6;-1:-1:-1;3392:54:42;1998:149;3665:154;3724:5;3769:2;3760:6;3755:3;3751:16;3747:25;3744:45;;;3785:1;3782;3775:12;3824:347;3875:8;3885:6;3939:3;3932:4;3924:6;3920:17;3916:27;3906:55;;3957:1;3954;3947:12;3906:55;-1:-1:-1;3980:20:42;;-1:-1:-1;;;;;4012:30:42;;4009:50;;;4055:1;4052;4045:12;4009:50;4092:4;4084:6;4080:17;4068:29;;4144:3;4137:4;4128:6;4120;4116:19;4112:30;4109:39;4106:59;;;4161:1;4158;4151:12;4106:59;3824:347;;;;;:::o;4176:1093::-;4317:6;4325;4333;4341;4349;4357;4365;4418:3;4406:9;4397:7;4393:23;4389:33;4386:53;;;4435:1;4432;4425:12;4386:53;4458;4503:7;4492:9;4458:53;:::i;:::-;4448:63;-1:-1:-1;4580:2:42;4565:18;;4552:32;;-1:-1:-1;4659:3:42;4644:19;;4631:33;-1:-1:-1;;;;;4676:30:42;;4673:50;;;4719:1;4716;4709:12;4673:50;4758:58;4808:7;4799:6;4788:9;4784:22;4758:58;:::i;:::-;4835:8;;-1:-1:-1;4732:84:42;-1:-1:-1;;4922:3:42;4907:19;;4894:33;4936;4894;4936;:::i;:::-;4988:7;-1:-1:-1;5048:3:42;5033:19;;5020:33;-1:-1:-1;;;;;5065:32:42;;5062:52;;;5110:1;5107;5100:12;5062:52;5149:60;5201:7;5190:8;5179:9;5175:24;5149:60;:::i;:::-;4176:1093;;;;-1:-1:-1;4176:1093:42;;-1:-1:-1;4176:1093:42;;;;5123:86;;-1:-1:-1;;;4176:1093:42:o;6249:508::-;6326:6;6334;6342;6395:2;6383:9;6374:7;6370:23;6366:32;6363:52;;;6411:1;6408;6401:12;6363:52;6450:9;6437:23;6469:31;6494:5;6469:31;:::i;:::-;6519:5;-1:-1:-1;6576:2:42;6561:18;;6548:32;6589:33;6548:32;6589:33;:::i;:::-;6249:508;;6641:7;;-1:-1:-1;;;6721:2:42;6706:18;;;;6693:32;;6249:508::o;6951:163::-;7018:20;;7078:10;7067:22;;7057:33;;7047:61;;7104:1;7101;7094:12;7047:61;6951:163;;;:::o;7119:298::-;7186:6;7194;7247:2;7235:9;7226:7;7222:23;7218:32;7215:52;;;7263:1;7260;7253:12;7215:52;7286:28;7304:9;7286:28;:::i;7422:118::-;7508:5;7501:13;7494:21;7487:5;7484:32;7474:60;;7530:1;7527;7520:12;7545:489;7639:6;7647;7700:2;7688:9;7679:7;7675:23;7671:32;7668:52;;;7716:1;7713;7706:12;7668:52;7756:9;7743:23;-1:-1:-1;;;;;7781:6:42;7778:30;7775:50;;;7821:1;7818;7811:12;7775:50;7844:69;7905:7;7896:6;7885:9;7881:22;7844:69;:::i;:::-;7834:79;;;7963:2;7952:9;7948:18;7935:32;7976:28;7998:5;7976:28;:::i;:::-;8023:5;8013:15;;;7545:489;;;;;:::o;8039:253::-;2072:12;;2060:25;;2134:4;2123:16;;;2117:23;2101:14;;;2094:47;8229:2;8214:18;;8241:45;1998:149;8297:159;8364:20;;8424:6;8413:18;;8403:29;;8393:57;;8446:1;8443;8436:12;8461:256;8527:6;8535;8588:2;8576:9;8567:7;8563:23;8559:32;8556:52;;;8604:1;8601;8594:12;8556:52;8627:28;8645:9;8627:28;:::i;:::-;8617:38;;8674:37;8707:2;8696:9;8692:18;8674:37;:::i;:::-;8664:47;;8461:256;;;;;:::o;9181:247::-;9240:6;9293:2;9281:9;9272:7;9268:23;9264:32;9261:52;;;9309:1;9306;9299:12;9261:52;9348:9;9335:23;9367:31;9392:5;9367:31;:::i;9638:668::-;9750:6;9758;9766;9774;9827:3;9815:9;9806:7;9802:23;9798:33;9795:53;;;9844:1;9841;9834:12;9795:53;9867;9912:7;9901:9;9867:53;:::i;:::-;9857:63;;9971:2;9960:9;9956:18;9943:32;-1:-1:-1;;;;;9990:6:42;9987:30;9984:50;;;10030:1;10027;10020:12;9984:50;10069:58;10119:7;10110:6;10099:9;10095:22;10069:58;:::i;:::-;10146:8;;-1:-1:-1;10043:84:42;-1:-1:-1;;10231:3:42;10216:19;;10203:33;10245:31;10203:33;10245:31;:::i;:::-;9638:668;;;;-1:-1:-1;9638:668:42;;-1:-1:-1;;9638:668:42:o;10311:395::-;10402:8;10412:6;10466:3;10459:4;10451:6;10447:17;10443:27;10433:55;;10484:1;10481;10474:12;10433:55;-1:-1:-1;10507:20:42;;-1:-1:-1;;;;;10539:30:42;;10536:50;;;10582:1;10579;10572:12;10536:50;10619:4;10611:6;10607:17;10595:29;;10679:3;10672:4;10662:6;10659:1;10655:14;10647:6;10643:27;10639:38;10636:47;10633:67;;;10696:1;10693;10686:12;10711:504;10836:6;10844;10897:2;10885:9;10876:7;10872:23;10868:32;10865:52;;;10913:1;10910;10903:12;10865:52;10953:9;10940:23;-1:-1:-1;;;;;10978:6:42;10975:30;10972:50;;;11018:1;11015;11008:12;10972:50;11057:98;11147:7;11138:6;11127:9;11123:22;11057:98;:::i;:::-;11174:8;;11031:124;;-1:-1:-1;10711:504:42;-1:-1:-1;;;;10711:504:42:o;11220:184::-;11278:6;11331:2;11319:9;11310:7;11306:23;11302:32;11299:52;;;11347:1;11344;11337:12;11299:52;11370:28;11388:9;11370:28;:::i;11591:553::-;11677:6;11685;11693;11701;11754:2;11742:9;11733:7;11729:23;11725:32;11722:52;;;11770:1;11767;11760:12;11722:52;11793:28;11811:9;11793:28;:::i;:::-;11783:38;;11840:37;11873:2;11862:9;11858:18;11840:37;:::i;:::-;11830:47;;11928:2;11917:9;11913:18;11900:32;-1:-1:-1;;;;;11947:6:42;11944:30;11941:50;;;11987:1;11984;11977:12;11941:50;12026:58;12076:7;12067:6;12056:9;12052:22;12026:58;:::i;:::-;11591:553;;;;-1:-1:-1;12103:8:42;-1:-1:-1;;;;11591:553:42:o;12652:655::-;12788:6;12796;12804;12848:9;12839:7;12835:23;12878:3;12874:2;12870:12;12867:32;;;12895:1;12892;12885:12;12867:32;12935:9;12922:23;-1:-1:-1;;;;;12960:6:42;12957:30;12954:50;;;13000:1;12997;12990:12;12954:50;13023:69;13084:7;13075:6;13064:9;13060:22;13023:69;:::i;:::-;13013:79;-1:-1:-1;;13126:2:42;-1:-1:-1;;13108:16:42;;13104:25;13101:45;;;13142:1;13139;13132:12;13101:45;;13180:2;13169:9;13165:18;13155:28;;13233:2;13222:9;13218:18;13205:32;13246:31;13271:5;13246:31;:::i;:::-;13296:5;13286:15;;;12652:655;;;;;:::o;13312:609::-;13552:4;13594:3;13583:9;13579:19;13571:27;;13631:6;13625:13;13614:9;13607:32;-1:-1:-1;;;;;13699:4:42;13691:6;13687:17;13681:24;13677:49;13670:4;13659:9;13655:20;13648:79;13774:4;13766:6;13762:17;13756:24;13789:62;13845:4;13834:9;13830:20;13816:12;2072;;2060:25;;2134:4;2123:16;;;2117:23;2101:14;;2094:47;1998:149;13789:62;-1:-1:-1;2072:12:42;;13910:3;13895:19;;2060:25;2134:4;2123:16;;2117:23;2101:14;;;2094:47;13860:55;1998:149;13926:388;13994:6;14002;14055:2;14043:9;14034:7;14030:23;14026:32;14023:52;;;14071:1;14068;14061:12;14023:52;14110:9;14097:23;14129:31;14154:5;14129:31;:::i;:::-;14179:5;-1:-1:-1;14236:2:42;14221:18;;14208:32;14249:33;14208:32;14249:33;:::i;14319:234::-;14402:6;14455:2;14443:9;14434:7;14430:23;14426:32;14423:52;;;14471:1;14468;14461:12;14423:52;14494:53;14539:7;14528:9;14494:53;:::i;14558:380::-;14637:1;14633:12;;;;14680;;;14701:61;;14755:4;14747:6;14743:17;14733:27;;14701:61;14808:2;14800:6;14797:14;14777:18;14774:38;14771:161;;14854:10;14849:3;14845:20;14842:1;14835:31;14889:4;14886:1;14879:15;14917:4;14914:1;14907:15;14943:251;15013:6;15066:2;15054:9;15045:7;15041:23;15037:32;15034:52;;;15082:1;15079;15072:12;15034:52;15114:9;15108:16;15133:31;15158:5;15133:31;:::i;15199:230::-;15269:6;15322:2;15310:9;15301:7;15297:23;15293:32;15290:52;;;15338:1;15335;15328:12;15290:52;-1:-1:-1;15383:16:42;;15199:230;-1:-1:-1;15199:230:42:o;15434:127::-;15495:10;15490:3;15486:20;15483:1;15476:31;15526:4;15523:1;15516:15;15550:4;15547:1;15540:15;15834:253;15906:2;15900:9;15948:4;15936:17;;-1:-1:-1;;;;;15968:34:42;;16004:22;;;15965:62;15962:88;;;16030:18;;:::i;:::-;16066:2;16059:22;15834:253;:::o;16092:257::-;16164:4;16158:11;;;16196:17;;-1:-1:-1;;;;;16228:34:42;;16264:22;;;16225:62;16222:88;;;16290:18;;:::i;16354:275::-;16425:2;16419:9;16490:2;16471:13;;-1:-1:-1;;16467:27:42;16455:40;;-1:-1:-1;;;;;16510:34:42;;16546:22;;;16507:62;16504:88;;;16572:18;;:::i;:::-;16608:2;16601:22;16354:275;;-1:-1:-1;16354:275:42:o;16634:186::-;16682:4;-1:-1:-1;;;;;16707:6:42;16704:30;16701:56;;;16737:18;;:::i;:::-;-1:-1:-1;16803:2:42;16782:15;-1:-1:-1;;16778:29:42;16809:4;16774:40;;16634:186::o;16825:1784::-;17017:9;-1:-1:-1;;;;;17047:6:42;17044:30;17041:56;;;17077:18;;:::i;:::-;17123:6;17120:1;17116:14;17150:30;17174:4;17170:2;17166:13;17150:30;:::i;:::-;17214:19;;;17286:14;;;;17258:4;17249:14;;;17323;17312:26;;17309:46;;;17351:1;17348;17341:12;17309:46;17375:5;17389:1187;17405:6;17400:3;17397:15;17389:1187;;;17493:3;17480:17;-1:-1:-1;;;;;17516:11:42;17513:35;17510:55;;;17561:1;17558;17551:12;17510:55;17588:23;;17656:4;17635:14;17631:23;;;17627:34;17624:54;;;17674:1;17671;17664:12;17624:54;17706:22;;:::i;:::-;17757:21;17775:2;17757:21;:::i;:::-;17748:7;17741:38;17819:32;17845:4;17841:2;17837:13;17819:32;:::i;:::-;17812:4;17803:7;17799:18;17792:60;17900:2;17896;17892:11;17879:25;-1:-1:-1;;;;;17923:6:42;17920:30;17917:50;;;17963:1;17960;17953:12;17917:50;17990:15;;;;;18047:14;18040:4;18032:13;;18028:34;18018:62;;18076:1;18073;18066:12;18018:62;18122:2;18109:16;18153:54;18169:37;18197:8;18169:37;:::i;:::-;18153:54;:::i;:::-;18236:8;18227:7;18220:25;18294:14;18287:4;18276:8;18272:2;18268:17;18264:28;18261:48;18258:68;;;18322:1;18319;18312:12;18258:68;18387:8;18380:4;18376:2;18372:13;18365:4;18356:7;18352:18;18339:57;18451:1;18444:4;18433:8;18424:7;18420:22;18416:33;18409:44;18491:7;18486:2;18477:7;18473:16;18466:33;;;18524:7;18519:3;18512:20;;;18561:4;18556:3;18552:14;18545:21;;17431:4;17426:3;17422:14;17415:21;;17389:1187;;;-1:-1:-1;18598:5:42;16825:1784;-1:-1:-1;;;;;16825:1784:42:o;18614:331::-;18719:9;18730;18772:8;18760:10;18757:24;18754:44;;;18794:1;18791;18784:12;18754:44;18823:6;18813:8;18810:20;18807:40;;;18843:1;18840;18833:12;18807:40;-1:-1:-1;;18869:23:42;;;18914:25;;;;;-1:-1:-1;18614:331:42:o;18950:476::-;19141:3;19179:6;19173:13;19195:66;19254:6;19249:3;19242:4;19234:6;19230:17;19195:66;:::i;:::-;19283:16;;19336:6;19328;19283:16;19308:35;19400:1;19362:18;;19389:13;;;-1:-1:-1;19362:18:42;;18950:476;-1:-1:-1;;;18950:476:42:o;19431:266::-;19519:6;19514:3;19507:19;19571:6;19564:5;19557:4;19552:3;19548:14;19535:43;-1:-1:-1;19623:1:42;19598:16;;;19616:4;19594:27;;;19587:38;;;;19679:2;19658:15;;;-1:-1:-1;;19654:29:42;19645:39;;;19641:50;;19431:266::o;19702:244::-;19859:2;19848:9;19841:21;19822:4;19879:61;19936:2;19925:9;19921:18;19913:6;19905;19879:61;:::i;19951:127::-;20012:10;20007:3;20003:20;20000:1;19993:31;20043:4;20040:1;20033:15;20067:4;20064:1;20057:15;20083:331;20182:4;20240:11;20227:25;20334:3;20330:8;20319;20303:14;20299:29;20295:44;20275:18;20271:69;20261:97;;20354:1;20351;20344:12;20261:97;20375:33;;;;;20083:331;-1:-1:-1;;20083:331:42:o;20419:521::-;20496:4;20502:6;20562:11;20549:25;20656:2;20652:7;20641:8;20625:14;20621:29;20617:43;20597:18;20593:68;20583:96;;20675:1;20672;20665:12;20583:96;20702:33;;20754:20;;;-1:-1:-1;;;;;;20786:30:42;;20783:50;;;20829:1;20826;20819:12;20783:50;20862:4;20850:17;;-1:-1:-1;20893:14:42;20889:27;;;20879:38;;20876:58;;;20930:1;20927;20920:12;20945:129;-1:-1:-1;;;;;21023:5:42;21019:30;21012:5;21009:41;20999:69;;21064:1;21061;21054:12;21079:1040;21453:10;21426:25;21444:6;21426:25;:::i;:::-;21422:42;21404:61;;21531:4;21519:17;;;21506:31;21553:20;;;21546:35;21385:4;21630;21618:17;;21605:31;21645:32;21605:31;21645:32;:::i;:::-;-1:-1:-1;;;;;21719:7:42;21715:32;21708:4;21697:9;21693:20;21686:62;;21784:6;21779:2;21768:9;21764:18;21757:34;21828:3;21822;21811:9;21807:19;21800:32;21855:62;21912:3;21901:9;21897:19;21889:6;21881;21855:62;:::i;:::-;-1:-1:-1;;;;;21954:32:42;;21974:3;21933:19;;21926:61;22024:22;;;22018:3;22003:19;;21996:51;22064:49;22028:6;22098;22090;22064:49;:::i;:::-;22056:57;21079:1040;-1:-1:-1;;;;;;;;;;21079:1040:42:o;22124:667::-;22203:6;22256:2;22244:9;22235:7;22231:23;22227:32;22224:52;;;22272:1;22269;22262:12;22224:52;22305:9;22299:16;-1:-1:-1;;;;;22330:6:42;22327:30;22324:50;;;22370:1;22367;22360:12;22324:50;22393:22;;22446:4;22438:13;;22434:27;-1:-1:-1;22424:55:42;;22475:1;22472;22465:12;22424:55;22508:2;22502:9;22533:52;22549:35;22577:6;22549:35;:::i;22533:52::-;22608:6;22601:5;22594:21;22656:7;22651:2;22642:6;22638:2;22634:15;22630:24;22627:37;22624:57;;;22677:1;22674;22667:12;22624:57;22690:71;22754:6;22749:2;22742:5;22738:14;22733:2;22729;22725:11;22690:71;:::i;23246:245::-;23304:6;23357:2;23345:9;23336:7;23332:23;23328:32;23325:52;;;23373:1;23370;23363:12;23325:52;23412:9;23399:23;23431:30;23455:5;23431:30;:::i;23496:479::-;23763:1;23759;23754:3;23750:11;23746:19;23738:6;23734:32;23723:9;23716:51;23803:6;23798:2;23787:9;23783:18;23776:34;23858:6;23850;23846:19;23841:2;23830:9;23826:18;23819:47;23902:3;23897:2;23886:9;23882:18;23875:31;23697:4;23923:46;23964:3;23953:9;23949:19;23941:6;23923:46;:::i;24598:379::-;24791:2;24780:9;24773:21;24754:4;24817:45;24858:2;24847:9;24843:18;24835:6;24817:45;:::i;:::-;24910:9;24902:6;24898:22;24893:2;24882:9;24878:18;24871:50;24938:33;24964:6;24956;24938:33;:::i;24982:245::-;25049:6;25102:2;25090:9;25081:7;25077:23;25073:32;25070:52;;;25118:1;25115;25108:12;25070:52;25150:9;25144:16;25169:28;25191:5;25169:28;:::i;25232:887::-;25451:2;25440:9;25433:21;25509:10;25500:6;25494:13;25490:30;25485:2;25474:9;25470:18;25463:58;25575:4;25567:6;25563:17;25557:24;25552:2;25541:9;25537:18;25530:52;25414:4;25629:2;25621:6;25617:15;25611:22;25670:4;25664:3;25653:9;25649:19;25642:33;25698:52;25745:3;25734:9;25730:19;25716:12;25698:52;:::i;:::-;25684:66;;25799:2;25791:6;25787:15;25781:22;25873:2;25869:7;25857:9;25849:6;25845:22;25841:36;25834:4;25823:9;25819:20;25812:66;25901:41;25935:6;25919:14;25901:41;:::i;:::-;26011:3;25999:16;;;;25993:23;25986:31;25979:39;25973:3;25958:19;;25951:68;-1:-1:-1;;;;;;;;26080:32:42;;;;26073:4;26058:20;;;26051:62;25887:55;25232:887::o;26124:388::-;26194:5;26242:4;26230:9;26225:3;26221:19;26217:30;26214:50;;;26260:1;26257;26250:12;26214:50;26282:22;;:::i;:::-;26349:16;;26374:22;;26462:2;26447:18;;;26441:25;26482:14;;;26475:31;;;;-1:-1:-1;26273:31:42;26124:388;-1:-1:-1;26124:388:42:o;26517:257::-;26615:6;26668:2;26656:9;26647:7;26643:23;26639:32;26636:52;;;26684:1;26681;26674:12;26636:52;26707:61;26760:7;26749:9;26707:61;:::i;26904:517::-;27005:2;27000:3;26997:11;26994:421;;;27041:5;27038:1;27031:16;27085:4;27082:1;27072:18;27155:2;27143:10;27139:19;27136:1;27132:27;27126:4;27122:38;27191:4;27179:10;27176:20;27173:47;;;-1:-1:-1;27214:4:42;27173:47;27269:2;27264:3;27260:12;27257:1;27253:20;27247:4;27243:31;27233:41;;27324:81;27342:2;27335:5;27332:13;27324:81;;;27401:1;27387:16;;27368:1;27357:13;27324:81;;27597:1295;27721:3;27715:10;-1:-1:-1;;;;;27740:6:42;27737:30;27734:56;;;27770:18;;:::i;:::-;27799:96;27888:6;27848:38;27880:4;27874:11;27848:38;:::i;:::-;27842:4;27799:96;:::i;:::-;27944:4;27975:2;27964:14;;27992:1;27987:648;;;;28679:1;28696:6;28693:89;;;-1:-1:-1;28748:19:42;;;28742:26;28693:89;-1:-1:-1;;27554:1:42;27550:11;;;27546:24;27542:29;27532:40;27578:1;27574:11;;;27529:57;28795:81;;27957:929;;27987:648;26851:1;26844:14;;;26888:4;26875:18;;-1:-1:-1;;28023:20:42;;;28140:222;28154:7;28151:1;28148:14;28140:222;;;28236:19;;;28230:26;28215:42;;28343:4;28328:20;;;;28296:1;28284:14;;;;28170:12;28140:222;;;28144:3;28390:6;28381:7;28378:19;28375:201;;;28451:19;;;28445:26;-1:-1:-1;;28534:1:42;28530:14;;;28546:3;28526:24;28522:37;28518:42;28503:58;28488:74;;28375:201;-1:-1:-1;;;;28622:1:42;28606:14;;;28602:22;28589:36;;-1:-1:-1;27597:1295:42:o;28897:1099::-;29113:4;29161:2;29150:9;29146:18;29191:2;29180:9;29173:21;29214:6;29249;29243:13;29280:6;29272;29265:22;29318:2;29307:9;29303:18;29296:25;;29380:2;29370:6;29367:1;29363:14;29352:9;29348:30;29344:39;29330:53;;29418:2;29410:6;29406:15;29439:1;29449:518;29463:6;29460:1;29457:13;29449:518;;;29556:2;29552:7;29540:9;29532:6;29528:22;29524:36;29519:3;29512:49;29590:6;29584:13;29640:10;29635:2;29629:9;29625:26;29617:6;29610:42;29713:6;29707:2;29703;29699:11;29693:18;29689:31;29684:2;29676:6;29672:15;29665:56;29768:2;29764;29760:11;29754:18;29734:38;;29809:4;29804:2;29796:6;29792:15;29785:29;29837:50;29881:4;29873:6;29869:17;29855:12;29837:50;:::i;:::-;29827:60;-1:-1:-1;;29922:2:42;29945:12;;;;29910:15;;;;;29485:1;29478:9;29449:518;;;-1:-1:-1;29984:6:42;;28897:1099;-1:-1:-1;;;;;;28897:1099:42:o;30001:487::-;30088:6;30148:2;30136:9;30127:7;30123:23;30119:32;30163:2;30160:22;;;30178:1;30175;30168:12;30160:22;-1:-1:-1;30220:22:42;;:::i;:::-;30287:23;;30319:22;;30414:2;30399:18;;;30386:32;30434:14;;;30427:31;;;;-1:-1:-1;30326:5:42;30001:487;-1:-1:-1;30001:487:42:o;30832:127::-;30893:10;30888:3;30884:20;30881:1;30874:31;30924:4;30921:1;30914:15;30948:4;30945:1;30938:15;30964:217;31004:1;31030;31020:132;;31074:10;31069:3;31065:20;31062:1;31055:31;31109:4;31106:1;31099:15;31137:4;31134:1;31127:15;31020:132;-1:-1:-1;31166:9:42;;30964:217::o;31186:168::-;31259:9;;;31290;;31307:15;;;31301:22;;31287:37;31277:71;;31328:18;;:::i;31359:255::-;31479:19;;31518:2;31510:11;;31507:101;;;-1:-1:-1;;31579:2:42;31575:12;;;31572:1;31568:20;31564:33;31553:45;31359:255;;;;:::o;31619:362::-;31739:19;;-1:-1:-1;;;;;;31776:37:42;;;31833:1;31825:10;;31822:153;;;-1:-1:-1;;;;;;31894:1:42;31890:11;;;31887:1;31883:19;31879:54;;;31871:63;;31867:98;;-1:-1:-1;31822:153:42;;31619:362;;;;:::o;31986:568::-;-1:-1:-1;;;;;32251:3:42;32247:28;32238:6;32233:3;32229:16;32225:51;32220:3;32213:64;32337:10;32332:3;32328:20;32319:6;32314:3;32310:16;32306:43;32302:1;32297:3;32293:11;32286:64;32380:6;32375:2;32370:3;32366:12;32359:28;32195:3;32416:6;32410:13;32432:75;32500:6;32495:2;32490:3;32486:12;32479:4;32471:6;32467:17;32432:75;:::i;:::-;32527:16;;;;32545:2;32523:25;;31986:568;-1:-1:-1;;;;;31986:568:42:o;32559:125::-;32624:9;;;32645:10;;;32642:36;;;32658:18;;:::i;32984:532::-;33225:6;33220:3;33213:19;-1:-1:-1;;;;;33288:3:42;33284:28;33275:6;33270:3;33266:16;33262:51;33257:2;33252:3;33248:12;33241:73;33344:6;33339:2;33334:3;33330:12;33323:28;33195:3;33380:6;33374:13;33396:73;33462:6;33457:2;33452:3;33448:12;33443:2;33435:6;33431:15;33396:73;:::i;:::-;33489:16;;;;33507:2;33485:25;;32984:532;-1:-1:-1;;;;;32984:532:42:o;33521:560::-;33623:6;33683:3;33671:9;33662:7;33658:23;33654:33;33699:2;33696:22;;;33714:1;33711;33704:12;33696:22;-1:-1:-1;33756:22:42;;:::i;:::-;33807:9;33801:16;33794:5;33787:31;33863:2;33852:9;33848:18;33842:25;33876:32;33900:7;33876:32;:::i;:::-;33935:2;33924:14;;33917:31;33980:70;34042:7;34037:2;34022:18;;33980:70;:::i;:::-;33975:2;33964:14;;33957:94;33968:5;33521:560;-1:-1:-1;;;33521:560:42:o
Swarm Source
ipfs://68198981facd40d56e4088c3bf4271ce2ed08ed24f71105748e8464517e41ecc
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in HYPE
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.