Latest 25 from a total of 10,542 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Approve | 50807598 | 35 mins ago | IN | 0 MON | 0.01018551 | ||||
| Approve | 50801768 | 1 hr ago | IN | 0 MON | 0.00813439 | ||||
| Approve | 50797653 | 1 hr ago | IN | 0 MON | 0.00814379 | ||||
| Approve | 50797119 | 1 hr ago | IN | 0 MON | 0.0054468 | ||||
| Approve | 50796910 | 1 hr ago | IN | 0 MON | 0.00812889 | ||||
| Transfer | 50792266 | 2 hrs ago | IN | 0 MON | 0.00478002 | ||||
| Approve | 50785537 | 3 hrs ago | IN | 0 MON | 0.01019834 | ||||
| Approve | 50775497 | 4 hrs ago | IN | 0 MON | 0.00813479 | ||||
| Transfer | 50775089 | 4 hrs ago | IN | 0 MON | 0.00986801 | ||||
| Approve | 50773761 | 4 hrs ago | IN | 0 MON | 0.01021341 | ||||
| Transfer | 50767201 | 5 hrs ago | IN | 0 MON | 0.00857806 | ||||
| Transfer | 50767062 | 5 hrs ago | IN | 0 MON | 0.00857586 | ||||
| Transfer | 50762887 | 5 hrs ago | IN | 0 MON | 0.00477743 | ||||
| Send | 50761328 | 5 hrs ago | IN | 5,363.36819522 MON | 0.102022 | ||||
| Approve | 50761307 | 5 hrs ago | IN | 0 MON | 0.00541958 | ||||
| Approve | 50759465 | 5 hrs ago | IN | 0 MON | 0.01020805 | ||||
| Approve | 50751755 | 6 hrs ago | IN | 0 MON | 0.00547052 | ||||
| Approve | 50751447 | 6 hrs ago | IN | 0 MON | 0.01530075 | ||||
| Approve | 50750349 | 6 hrs ago | IN | 0 MON | 0.00812961 | ||||
| Approve | 50745660 | 7 hrs ago | IN | 0 MON | 0.00818774 | ||||
| Transfer | 50745552 | 7 hrs ago | IN | 0 MON | 0.00990099 | ||||
| Approve | 50744412 | 7 hrs ago | IN | 0 MON | 0.00714035 | ||||
| Transfer | 50744284 | 7 hrs ago | IN | 0 MON | 0.00985959 | ||||
| Approve | 50739450 | 8 hrs ago | IN | 0 MON | 0.00501038 | ||||
| Approve | 50739407 | 8 hrs ago | IN | 0 MON | 0.00812184 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 50761328 | 5 hrs ago | 5,363.36819522 MON | ||||
| 50717788 | 10 hrs ago | 28.63801712 MON | ||||
| 50703916 | 12 hrs ago | 59.30842146 MON | ||||
| 50690844 | 13 hrs ago | 58.32794653 MON | ||||
| 50687081 | 13 hrs ago | 57.99527065 MON | ||||
| 50645852 | 18 hrs ago | 5,306.44733351 MON | ||||
| 50632002 | 20 hrs ago | 5,340.45393858 MON | ||||
| 50627872 | 20 hrs ago | 28.37255348 MON | ||||
| 50627245 | 20 hrs ago | 29.37045465 MON | ||||
| 50535673 | 30 hrs ago | 57.38928233 MON | ||||
| 50527706 | 31 hrs ago | 56.35096958 MON | ||||
| 50431463 | 42 hrs ago | 29.72337049 MON | ||||
| 50351788 | 2 days ago | 58.67643315 MON | ||||
| 50342817 | 2 days ago | 29.88087183 MON | ||||
| 50317275 | 2 days ago | 29.72337049 MON | ||||
| 50279223 | 2 days ago | 5,247.96641301 MON | ||||
| 50259691 | 2 days ago | 5,366.2463107 MON | ||||
| 50225343 | 2 days ago | 5,216.48408972 MON | ||||
| 50222135 | 2 days ago | 5,260.3892688 MON | ||||
| 50220327 | 2 days ago | 67.19385142 MON | ||||
| 50197717 | 2 days ago | 5,558.64369093 MON | ||||
| 50190693 | 2 days ago | 5,351.88654 MON | ||||
| 50189714 | 2 days ago | 80.71369169 MON | ||||
| 50182538 | 2 days ago | 5,445.14021236 MON | ||||
| 50181154 | 2 days ago | 92.19830093 MON |
Loading...
Loading
Contract Name:
WBTCOFT
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import { OFTFee } from "./OFTFee.sol";
contract WBTCOFT is OFTFee {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _owner
) OFTFee(_name, _symbol, _lzEndpoint, _owner) {}
function decimals() public pure override returns (uint8) {
return 8;
}
function sharedDecimals() public pure override returns (uint8) {
return 8;
}
}// 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 { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { FeeConfig, IFee } from "./interfaces/IFee.sol";
/**
* @title Fee
* @notice Implements fee configuration and calculation.
*/
abstract contract Fee is IFee, Ownable {
uint16 public constant BPS_DENOMINATOR = 10_000;
/**
* @dev Default fee basis points (BPS) for all destinations.
*/
uint16 public defaultFeeBps;
/**
* @dev Fee configuration for a specific destination LayerZero endpoint ID.
*/
mapping(uint32 dstEid => FeeConfig config) public feeBps;
/**
* @dev Sets the default fee basis points (BPS) for all destinations.
*/
function setDefaultFeeBps(uint16 _feeBps) external onlyOwner {
if (_feeBps > BPS_DENOMINATOR) revert IFee.InvalidBps();
defaultFeeBps = _feeBps;
emit DefaultFeeBpsSet(_feeBps);
}
/**
* @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID.
*/
function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external onlyOwner {
if (_feeBps > BPS_DENOMINATOR) revert IFee.InvalidBps();
feeBps[_dstEid] = FeeConfig(_feeBps, _enabled);
emit FeeBpsSet(_dstEid, _feeBps, _enabled);
}
/**
* @dev Returns the fee for a specific destination LayerZero EndpointV2 ID.
*/
function getFee(uint32 _dstEid, uint256 _amount) public view virtual returns (uint256) {
uint16 bps = _getFeeBps(_dstEid);
return bps == 0 ? 0 : (_amount * bps) / BPS_DENOMINATOR;
}
function _getFeeBps(uint32 _dstEid) internal view returns (uint16) {
FeeConfig memory config = feeBps[_dstEid];
return config.enabled ? config.feeBps : defaultFeeBps;
}
}// SPDX-LICENSE-IDENTIFIER: MIT
pragma solidity ^0.8.0;
struct FeeConfig {
uint16 feeBps;
bool enabled;
}
/**
* @title Fee interface.
* @notice A generic interface for collecting fees.
*/
interface IFee {
// errors
error InvalidBps();
error InvalidFeeOwner();
// events
event FeeBpsSet(uint32 dstEid, uint16 feeBps, bool enabled);
event DefaultFeeBpsSet(uint16 feeBps);
// setters
/**
* @dev Sets the default fee basis points (BPS) for all destinations.
*/
function setDefaultFeeBps(uint16 _feeBps) external;
/**
* @dev Sets the fee basis points (BPS) for a specific destination LayerZero EndpointV2 ID.
*/
function setFeeBps(uint32 _dstEid, uint16 _feeBps, bool _enabled) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
/// @title Interface for mintable and burnable tokens
interface IMintableBurnable {
/**
* @notice Burns tokens from a specified account
* @param _from Address from which tokens will be burned
* @param _amount Amount of tokens to be burned
* @return success Indicates whether the operation was successful
*/
function burn(address _from, uint256 _amount) external returns (bool success);
/**
* @notice Mints tokens to a specified account
* @param _to Address to which tokens will be minted
* @param _amount Amount of tokens to be minted
* @return success Indicates whether the operation was successful
*/
function mint(address _to, uint256 _amount) external returns (bool success);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { MessagingReceipt, MessagingFee } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol";
/**
* @dev Struct representing token parameters for the OFT send() operation.
*/
struct SendParam {
uint32 dstEid; // Destination endpoint ID.
bytes32 to; // Recipient address.
uint256 amountLD; // Amount to send in local decimals.
uint256 minAmountLD; // Minimum amount to send in local decimals.
bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
bytes composeMsg; // The composed message for the send() operation.
bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}
/**
* @dev Struct representing OFT limit information.
* @dev These amounts can change dynamically and are up the specific oft implementation.
*/
struct OFTLimit {
uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.
uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.
}
/**
* @dev Struct representing OFT receipt information.
*/
struct OFTReceipt {
uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
// @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}
/**
* @dev Struct representing OFT fee details.
* @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.
*/
struct OFTFeeDetail {
int256 feeAmountLD; // Amount of the fee in local decimals.
string description; // Description of the fee.
}
/**
* @title IOFT
* @dev Interface for the OftChain (OFT) token.
* @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.
* @dev This specific interface ID is '0x02e49c2c'.
*/
interface IOFT {
// Custom error messages
error InvalidLocalDecimals();
error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);
error AmountSDOverflowed(uint256 amountSD);
// Events
event OFTSent(
bytes32 indexed guid, // GUID of the OFT message.
uint32 dstEid, // Destination Endpoint ID.
address indexed fromAddress, // Address of the sender on the src chain.
uint256 amountSentLD, // Amount of tokens sent in local decimals.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
event OFTReceived(
bytes32 indexed guid, // GUID of the OFT message.
uint32 srcEid, // Source Endpoint ID.
address indexed toAddress, // Address of the recipient on the dst chain.
uint256 amountReceivedLD // Amount of tokens received in local decimals.
);
/**
* @notice Retrieves interfaceID and the version of the OFT.
* @return interfaceId The interface ID.
* @return version The version.
*
* @dev interfaceId: This specific interface ID is '0x02e49c2c'.
* @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
* @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
* ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
*/
function oftVersion() external view returns (bytes4 interfaceId, uint64 version);
/**
* @notice Retrieves the address of the token associated with the OFT.
* @return token The address of the ERC20 token implementation.
*/
function token() external view returns (address);
/**
* @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*
* @dev Allows things like wallet implementers to determine integration requirements,
* without understanding the underlying token implementation.
*/
function approvalRequired() external view returns (bool);
/**
* @notice Retrieves the shared decimals of the OFT.
* @return sharedDecimals The shared decimals of the OFT.
*/
function sharedDecimals() external view returns (uint8);
/**
* @notice Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.
* @param _sendParam The parameters for the send operation.
* @return limit The OFT limit information.
* @return oftFeeDetails The details of OFT fees.
* @return receipt The OFT receipt information.
*/
function quoteOFT(
SendParam calldata _sendParam
) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);
/**
* @notice Provides a quote for the send() operation.
* @param _sendParam The parameters for the send() operation.
* @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.
* @return fee The calculated LayerZero messaging fee from the send() operation.
*
* @dev MessagingFee: LayerZero msg fee
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
*/
function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);
/**
* @notice Executes the send() operation.
* @param _sendParam The parameters for the send operation.
* @param _fee The fee information supplied by the caller.
* - nativeFee: The native fee.
* - lzTokenFee: The lzToken fee.
* @param _refundAddress The address to receive any excess funds from fees etc. on the src.
* @return receipt The LayerZero messaging receipt from the send() operation.
* @return oftReceipt The OFT receipt information.
*
* @dev MessagingReceipt: LayerZero msg receipt
* - guid: The unique identifier for the sent message.
* - nonce: The nonce of the sent message.
* - fee: The LayerZero fee incurred for the message.
*/
function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable returns (MessagingReceipt memory, OFTReceipt memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library OFTComposeMsgCodec {
// Offset constants for decoding composed messages
uint8 private constant NONCE_OFFSET = 8;
uint8 private constant SRC_EID_OFFSET = 12;
uint8 private constant AMOUNT_LD_OFFSET = 44;
uint8 private constant COMPOSE_FROM_OFFSET = 76;
/**
* @dev Encodes a OFT composed message.
* @param _nonce The nonce value.
* @param _srcEid The source endpoint ID.
* @param _amountLD The amount in local decimals.
* @param _composeMsg The composed message.
* @return _msg The encoded Composed message.
*/
function encode(
uint64 _nonce,
uint32 _srcEid,
uint256 _amountLD,
bytes memory _composeMsg // 0x[composeFrom][composeMsg]
) internal pure returns (bytes memory _msg) {
_msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
}
/**
* @dev Retrieves the nonce for the composed message.
* @param _msg The message.
* @return The nonce value.
*/
function nonce(bytes calldata _msg) internal pure returns (uint64) {
return uint64(bytes8(_msg[:NONCE_OFFSET]));
}
/**
* @dev Retrieves the source endpoint ID for the composed message.
* @param _msg The message.
* @return The source endpoint ID.
*/
function srcEid(bytes calldata _msg) internal pure returns (uint32) {
return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
}
/**
* @dev Retrieves the amount in local decimals from the composed message.
* @param _msg The message.
* @return The amount in local decimals.
*/
function amountLD(bytes calldata _msg) internal pure returns (uint256) {
return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
}
/**
* @dev Retrieves the composeFrom value from the composed message.
* @param _msg The message.
* @return The composeFrom value.
*/
function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
}
/**
* @dev Retrieves the composed message.
* @param _msg The message.
* @return The composed message.
*/
function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
return _msg[COMPOSE_FROM_OFFSET:];
}
/**
* @dev Converts an address to bytes32.
* @param _addr The address to convert.
* @return The bytes32 representation of the address.
*/
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
/**
* @dev Converts bytes32 to an address.
* @param _b The bytes32 value to convert.
* @return The address representation of bytes32.
*/
function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
return address(uint160(uint256(_b)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library OFTMsgCodec {
// Offset constants for encoding and decoding OFT messages
uint8 private constant SEND_TO_OFFSET = 32;
uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;
/**
* @dev Encodes an OFT LayerZero message.
* @param _sendTo The recipient address.
* @param _amountShared The amount in shared decimals.
* @param _composeMsg The composed message.
* @return _msg The encoded message.
* @return hasCompose A boolean indicating whether the message has a composed payload.
*/
function encode(
bytes32 _sendTo,
uint64 _amountShared,
bytes memory _composeMsg
) internal view returns (bytes memory _msg, bool hasCompose) {
hasCompose = _composeMsg.length > 0;
// @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.
_msg = hasCompose
? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)
: abi.encodePacked(_sendTo, _amountShared);
}
/**
* @dev Checks if the OFT message is composed.
* @param _msg The OFT message.
* @return A boolean indicating whether the message is composed.
*/
function isComposed(bytes calldata _msg) internal pure returns (bool) {
return _msg.length > SEND_AMOUNT_SD_OFFSET;
}
/**
* @dev Retrieves the recipient address from the OFT message.
* @param _msg The OFT message.
* @return The recipient address.
*/
function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
return bytes32(_msg[:SEND_TO_OFFSET]);
}
/**
* @dev Retrieves the amount in shared decimals from the OFT message.
* @param _msg The OFT message.
* @return The amount in shared decimals.
*/
function amountSD(bytes calldata _msg) internal pure returns (uint64) {
return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));
}
/**
* @dev Retrieves the composed message from the OFT message.
* @param _msg The OFT message.
* @return The composed message.
*/
function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
return _msg[SEND_AMOUNT_SD_OFFSET:];
}
/**
* @dev Converts an address to bytes32.
* @param _addr The address to convert.
* @return The bytes32 representation of the address.
*/
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
/**
* @dev Converts bytes32 to an address.
* @param _b The bytes32 value to convert.
* @return The address representation of bytes32.
*/
function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
return address(uint160(uint256(_b)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
// External imports
import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
// Local imports
import { IMintableBurnable } from "./interfaces/IMintableBurnable.sol";
import { OFTCore } from "./OFTCore.sol";
/**
* @title MintBurnOFTAdapter
* @notice A variant of the standard OFT Adapter that uses an existing ERC20's mint and burn mechanisms for cross-chain transfers.
*
* @dev Inherits from OFTCore and provides implementations for _debit and _credit functions using a mintable and burnable token.
*/
abstract contract MintBurnOFTAdapter is OFTCore {
/// @dev The underlying ERC20 token.
IERC20 internal immutable innerToken;
/// @notice The contract responsible for minting and burning tokens.
IMintableBurnable public immutable minterBurner;
/**
* @notice Initializes the MintBurnOFTAdapter contract.
*
* @param _token The address of the underlying ERC20 token.
* @param _minterBurner The contract responsible for minting and burning tokens.
* @param _lzEndpoint The LayerZero endpoint address.
* @param _delegate The address of the delegate.
*
* @dev Calls the OFTCore constructor with the token's decimals, the endpoint, and the delegate.
*/
constructor(
address _token,
IMintableBurnable _minterBurner,
address _lzEndpoint,
address _delegate
) OFTCore(IERC20Metadata(_token).decimals(), _lzEndpoint, _delegate) {
innerToken = IERC20(_token);
minterBurner = _minterBurner;
}
/**
* @notice Retrieves the address of the underlying ERC20 token.
*
* @return The address of the adapted ERC20 token.
*
* @dev In the case of MintBurnOFTAdapter, 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 underlying token to send.
*
* @return requiresApproval True if approval is required, false otherwise.
*
* @dev In this MintBurnOFTAdapter, approval is NOT required because it uses mint and burn privileges.
*/
function approvalRequired() external pure virtual returns (bool) {
return false;
}
/**
* @notice Burns tokens from the sender's balance to prepare for sending.
*
* @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.
*
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, i.e., 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);
// Burns tokens from the caller.
minterBurner.burn(_from, amountSentLD);
}
/**
* @notice Mints tokens to the specified address upon receiving them.
*
* @param _to The address to credit the tokens to.
* @param _amountLD The amount of tokens to credit in local decimals.
*
* @return amountReceivedLD The amount of tokens actually received in local decimals.
*
* @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, i.e., 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) {
if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0)
// Mints the tokens and transfers to the recipient.
minterBurner.mint(_to, _amountLD);
// In the case of NON-default OFTAdapter, the amountLD MIGHT not be equal to amountReceivedLD.
return _amountLD;
}
}// 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.
*
* @dev Reverts if the _amountLD in shared decimals overflows uint64.
* @dev eg. uint(2**64 + 123) with a conversion rate of 1 wraps around 2**64 to uint(123).
*/
function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {
uint256 _amountSD = _amountLD / decimalConversionRate;
if (_amountSD > type(uint64).max) revert AmountSDOverflowed(_amountSD);
return uint64(_amountSD);
}
/**
* @dev Internal function to mock the amount mutation from a OFT debit() operation.
* @param _amountLD The amount to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @dev _dstEid The destination endpoint ID.
* @return amountSentLD The amount sent, in local decimals.
* @return amountReceivedLD The amount to be received on the remote chain, in local decimals.
*
* @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.
*/
function _debitView(
uint256 _amountLD,
uint256 _minAmountLD,
uint32 /*_dstEid*/
) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {
// @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.
amountSentLD = _removeDust(_amountLD);
// @dev The amount to send is the same as amount received in the default implementation.
amountReceivedLD = amountSentLD;
// @dev Check for slippage.
if (amountReceivedLD < _minAmountLD) {
revert SlippageExceeded(amountReceivedLD, _minAmountLD);
}
}
/**
* @dev Internal function to perform a debit operation.
* @param _from The address to debit.
* @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: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol";
import { Fee } from "@layerzerolabs/oft-evm/contracts/Fee.sol";
/**
* @title OFTFee Contract
* @notice OFT with fees.
*/
abstract contract OFTFee is OFT, Fee {
address public feeOwner;
event FeeOwnerSet(address _feeOwner);
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _owner
) OFT(_name, _symbol, _lzEndpoint, _owner) Ownable(_owner) {
feeOwner = _owner;
}
function setFeeOwner(address _feeOwner) external onlyOwner {
if (_feeOwner == address(0)) revert InvalidFeeOwner();
feeOwner = _feeOwner;
emit FeeOwnerSet(_feeOwner);
}
function _debitView(
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal view virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
amountSentLD = _amountLD;
// @dev Apply the fee, then de-dust the amount afterwards.
// This means the fee is taken from the amount before the dust is removed.
uint256 fee = getFee(_dstEid, _amountLD);
amountReceivedLD = _removeDust(_amountLD - fee);
// @dev Check for slippage.
if (amountReceivedLD < _minAmountLD) {
revert SlippageExceeded(amountReceivedLD, _minAmountLD);
}
}
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
(amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);
uint256 fee = amountSentLD - amountReceivedLD;
if (fee > 0) {
_transfer(_from, feeOwner, fee);
}
_burn(_from, amountReceivedLD);
}
}{
"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":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"amountSD","type":"uint256"}],"name":"AmountSDOverflowed","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidBps","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[],"name":"InvalidFeeOwner","type":"error"},{"inputs":[],"name":"InvalidLocalDecimals","type":"error"},{"inputs":[{"internalType":"bytes","name":"options","type":"bytes"}],"name":"InvalidOptions","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"name":"SimulationResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"}],"name":"DefaultFeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"indexed":false,"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"EnforcedOptionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"dstEid","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"feeBps","type":"uint16"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"FeeBpsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_feeOwner","type":"address"}],"name":"FeeOwnerSet","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":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_AND_CALL","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"pure","type":"function"},{"inputs":[],"name":"defaultFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"}],"name":"enforcedOptions","outputs":[{"internalType":"bytes","name":"enforcedOption","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstEid","type":"uint32"}],"name":"feeBps","outputs":[{"internalType":"uint16","name":"feeBps","type":"uint16"},{"internalType":"bool","name":"enabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"uint16","name":"_feeBps","type":"uint16"}],"name":"setDefaultFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"setDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"uint16","name":"msgType","type":"uint16"},{"internalType":"bytes","name":"options","type":"bytes"}],"internalType":"struct EnforcedOptionParam[]","name":"_enforcedOptions","type":"tuple[]"}],"name":"setEnforcedOptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"uint16","name":"_feeBps","type":"uint16"},{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeOwner","type":"address"}],"name":"setFeeOwner","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
60c06040523480156200001157600080fd5b5060405162003c1038038062003c108339810160408190526200003491620002fb565b8383838383838383838360088484818181818d6001600160a01b0381166200007657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200008181620001c6565b506001600160a01b038083166080528116620000b057604051632d618d8160e21b815260040160405180910390fd5b60805160405163ca5eb5e160e01b81526001600160a01b0383811660048301529091169063ca5eb5e190602401600060405180830381600087803b158015620000f857600080fd5b505af11580156200010d573d6000803e3d6000fd5b505050505050505062000125620001c160201b60201c565b60ff168360ff1610156200014c576040516301e9714b60e41b815260040160405180910390fd5b62000159600884620003a0565b6200016690600a620004bf565b60a05250600891506200017c9050838262000568565b5060096200018b828262000568565b5050600c80546001600160a01b0319166001600160a01b03979097169690961790955550620006349a5050505050505050505050565b600890565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200023e57600080fd5b81516001600160401b03808211156200025b576200025b62000216565b604051601f8301601f19908116603f0116810190828211818310171562000286576200028662000216565b8160405283815260209250866020858801011115620002a457600080fd5b600091505b83821015620002c85785820183015181830184015290820190620002a9565b6000602085830101528094505050505092915050565b80516001600160a01b0381168114620002f657600080fd5b919050565b600080600080608085870312156200031257600080fd5b84516001600160401b03808211156200032a57600080fd5b62000338888389016200022c565b955060208701519150808211156200034f57600080fd5b506200035e878288016200022c565b9350506200036f60408601620002de565b91506200037f60608601620002de565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b60ff8281168282160390811115620003bc57620003bc6200038a565b92915050565b600181815b8085111562000403578160001904821115620003e757620003e76200038a565b80851615620003f557918102915b93841c9390800290620003c7565b509250929050565b6000826200041c57506001620003bc565b816200042b57506000620003bc565b81600181146200044457600281146200044f576200046f565b6001915050620003bc565b60ff8411156200046357620004636200038a565b50506001821b620003bc565b5060208310610133831016604e8410600b841016171562000494575081810a620003bc565b620004a08383620003c2565b8060001904821115620004b757620004b76200038a565b029392505050565b6000620004d060ff8416836200040b565b9392505050565b600181811c90821680620004ec57607f821691505b6020821081036200050d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000563576000816000526020600020601f850160051c810160208610156200053e5750805b601f850160051c820191505b818110156200055f578281556001016200054a565b5050505b505050565b81516001600160401b0381111562000584576200058462000216565b6200059c81620005958454620004d7565b8462000513565b602080601f831160018114620005d45760008415620005bb5750858301515b600019600386901b1c1916600185901b1785556200055f565b600085815260208120601f198616915b828110156200060557888601518255948401946001909101908401620005e4565b5085821015620006245787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051613570620006a06000396000818161076101528181611e7f01528181611ef401526120f901526000818161060501528181610be10152818161140e015281816116a101528181611a0c0152818161224b015281816123bb015261247201526135706000f3fe6080604052600436106102c95760003560e01c8063715018a611610175578063bb0b6a53116100dc578063d045a0dc11610095578063e1a452181161006f578063e1a452181461094c578063f2fde38b14610962578063fc0c546a14610569578063ff7bd03d1461098257600080fd5b8063d045a0dc146108d3578063d4243885146108e6578063dd62ed3e1461090657600080fd5b8063bb0b6a5314610817578063bc70b35414610844578063bcae25a414610864578063bd815db01461087f578063c7c7f5b314610892578063ca5eb5e1146108b357600080fd5b8063963efcaa1161012e578063963efcaa1461074f5780639f68b96414610783578063a9059cbb14610797578063b731ea0a146107b7578063b9818be1146107d7578063b98bd070146107f757600080fd5b8063715018a61461069d5780637d25a05e146106b257806382413eac146106ed578063857749b01461046a5780638da5cb5b1461071c57806395d89b411461073a57600080fd5b80633194c180116102345780635535d461116101ed5780635e280f11116101c75780635e280f11146105f35780636db7bcdb146106275780636fc1b31e1461064757806370a082311461066757600080fd5b80635535d4611461057c5780635a0dfe4d1461059c5780635bf9c226146105d357600080fd5b80633194c180146104865780633400288b146104dc5780633b6f743b146104fc5780634488b652146105295780634b104eff1461054957806352ae28791461056957600080fd5b8063156a0d0f11610286578063156a0d0f146103cd57806317442b70146103f457806318160ddd146104165780631f5e13341461043557806323b872dd1461044a578063313ce5671461046a57600080fd5b806306fdde03146102ce578063095ea7b3146102f95780630d35b41514610329578063111ecdad1461035857806313137d6514610390578063134d4f25146103a5575b600080fd5b3480156102da57600080fd5b506102e36109a2565b6040516102f091906125ea565b60405180910390f35b34801561030557600080fd5b50610319610314366004612612565b610a34565b60405190151581526020016102f0565b34801561033557600080fd5b50610349610344366004612656565b610a4e565b6040516102f09392919061268a565b34801561036457600080fd5b50600454610378906001600160a01b031681565b6040516001600160a01b0390911681526020016102f0565b6103a361039e36600461277d565b610bdf565b005b3480156103b157600080fd5b506103ba600281565b60405161ffff90911681526020016102f0565b3480156103d957600080fd5b506040805162b9270b60e21b815260016020820152016102f0565b34801561040057600080fd5b50604080516001815260026020820152016102f0565b34801561042257600080fd5b506007545b6040519081526020016102f0565b34801561044157600080fd5b506103ba600181565b34801561045657600080fd5b5061031961046536600461281c565b610c9f565b34801561047657600080fd5b50604051600881526020016102f0565b34801561049257600080fd5b506104c26104a1366004612876565b600b6020526000908152604090205461ffff81169062010000900460ff1682565b6040805161ffff90931683529015156020830152016102f0565b3480156104e857600080fd5b506103a36104f7366004612891565b610cc5565b34801561050857600080fd5b5061051c6105173660046128bb565b610cdb565b6040516102f0919061290c565b34801561053557600080fd5b506103a3610544366004612935565b610d42565b34801561055557600080fd5b506103a3610564366004612950565b610dbc565b34801561057557600080fd5b5030610378565b34801561058857600080fd5b506102e361059736600461296d565b610e3c565b3480156105a857600080fd5b506103196105b7366004612891565b63ffffffff919091166000908152600160205260409020541490565b3480156105df57600080fd5b506104276105ee366004612891565b610ee1565b3480156105ff57600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b34801561063357600080fd5b506103a36106423660046129a0565b610f24565b34801561065357600080fd5b506103a3610662366004612950565b610fe1565b34801561067357600080fd5b50610427610682366004612950565b6001600160a01b031660009081526005602052604090205490565b3480156106a957600080fd5b506103a3611037565b3480156106be57600080fd5b506106d56106cd366004612891565b600092915050565b6040516001600160401b0390911681526020016102f0565b3480156106f957600080fd5b506103196107083660046129e7565b6001600160a01b0381163014949350505050565b34801561072857600080fd5b506000546001600160a01b0316610378565b34801561074657600080fd5b506102e361104b565b34801561075b57600080fd5b506104277f000000000000000000000000000000000000000000000000000000000000000081565b34801561078f57600080fd5b506000610319565b3480156107a357600080fd5b506103196107b2366004612612565b61105a565b3480156107c357600080fd5b50600254610378906001600160a01b031681565b3480156107e357600080fd5b50600c54610378906001600160a01b031681565b34801561080357600080fd5b506103a3610812366004612a91565b611068565b34801561082357600080fd5b50610427610832366004612876565b60016020526000908152604090205481565b34801561085057600080fd5b506102e361085f366004612ad2565b611082565b34801561087057600080fd5b50600a546103ba9061ffff1681565b6103a361088d366004612a91565b61122a565b6108a56108a0366004612b32565b6113b4565b6040516102f0929190612b94565b3480156108bf57600080fd5b506103a36108ce366004612950565b6113e7565b6103a36108e136600461277d565b61146d565b3480156108f257600080fd5b506103a3610901366004612950565b61149c565b34801561091257600080fd5b50610427610921366004612be6565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b34801561095857600080fd5b506103ba61271081565b34801561096e57600080fd5b506103a361097d366004612950565b6114f2565b34801561098e57600080fd5b5061031961099d366004612c14565b611530565b6060600880546109b190612c30565b80601f01602080910402602001604051908101604052809291908181526020018280546109dd90612c30565b8015610a2a5780601f106109ff57610100808354040283529160200191610a2a565b820191906000526020600020905b815481529060010190602001808311610a0d57829003601f168201915b5050505050905090565b600033610a42818585611566565b60019150505b92915050565b60408051808201909152600080825260208201526060610a81604051806040016040528060008152602001600081525090565b600080306001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae69190612c64565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b479190612c81565b60408051808201825284815260208082018490528251600080825291810190935290975091925090610b9c565b604080518082019091526000815260606020820152815260200190600190039081610b745790505b509350600080610bc1604089013560608a0135610bbc60208c018c612876565b611578565b60408051808201909152918252602082015296989597505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610c2f576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610c4990610c44908a612876565b6115d0565b14610c8757610c5b6020880188612876565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610c26565b610c968787878787878761160c565b50505050505050565b600033610cad858285611773565b610cb88585856117f2565b60019150505b9392505050565b610ccd611851565b610cd7828261187e565b5050565b60408051808201909152600080825260208201526000610d0b60408501356060860135610bbc6020880188612876565b915050600080610d1b86846118d3565b9092509050610d38610d306020880188612876565b8383886119f6565b9695505050505050565b610d4a611851565b61271061ffff82161115610d715760405163c6cc5d7f60e01b815260040160405180910390fd5b600a805461ffff191661ffff83169081179091556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a150565b610dc4611851565b6001600160a01b038116610dee576040516001628bfb2560e01b0319815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f235247fd708c3a4799d15b30e49e97ff43e74e18a909590c0a9f257a379e19f890602001610db1565b600360209081526000928352604080842090915290825290208054610e6090612c30565b80601f0160208091040260200160405190810160405280929190818152602001828054610e8c90612c30565b8015610ed95780601f10610eae57610100808354040283529160200191610ed9565b820191906000526020600020905b815481529060010190602001808311610ebc57829003601f168201915b505050505081565b600080610eed84611ad7565b905061ffff811615610f1957612710610f0a61ffff831685612cc6565b610f149190612cdd565b610f1c565b60005b949350505050565b610f2c611851565b61271061ffff83161115610f535760405163c6cc5d7f60e01b815260040160405180910390fd5b60408051808201825261ffff848116808352841515602080850182815263ffffffff8a166000818152600b84528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201527f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a1505050565b610fe9611851565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001610db1565b61103f611851565b6110496000611b28565b565b6060600980546109b190612c30565b600033610a428185856117f2565b611070611851565b610cd761107d8284612da0565b611b78565b63ffffffff8416600090815260036020908152604080832061ffff871684529091528120805460609291906110b690612c30565b80601f01602080910402602001604051908101604052809291908181526020018280546110e290612c30565b801561112f5780601f106111045761010080835404028352916020019161112f565b820191906000526020600020905b81548152906001019060200180831161111257829003601f168201915b50505050509050805160000361117f5783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610f1c9350505050565b600083900361118f579050610f1c565b6002831061120d576111d684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c7f92505050565b806111e48460028188612eb5565b6040516020016111f693929190612edf565b604051602081830303815290604052915050610f1c565b8383604051639a6d49cd60e01b8152600401610c26929190612f30565b60005b81811015611333573683838381811061124857611248612f44565b905060200281019061125a9190612f5a565b905061128d61126c6020830183612876565b602083013563ffffffff919091166000908152600160205260409020541490565b611297575061132b565b3063d045a0dc60c08301358360a08101356112b6610100830183612f7b565b6112c7610100890160e08a01612950565b6112d56101208a018a612f7b565b6040518963ffffffff1660e01b81526004016112f79796959493929190612fd6565b6000604051808303818588803b15801561131057600080fd5b505af1158015611324573d6000803e3d6000fd5b5050505050505b60010161122d565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611372573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261139a919081019061305c565b604051638351eea760e01b8152600401610c2691906125ea565b6113bc612553565b60408051808201909152600080825260208201526113db858585611cab565b91509150935093915050565b6113ef611851565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063ca5eb5e190602401600060405180830381600087803b15801561145257600080fd5b505af1158015611466573d6000803e3d6000fd5b5050505050565b33301461148d5760405163029a949d60e31b815260040160405180910390fd5b610c9687878787878787610c87565b6114a4611851565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610db1565b6114fa611851565b6001600160a01b03811661152457604051631e4fbdf760e01b815260006004820152602401610c26565b61152d81611b28565b50565b60006020820180359060019083906115489086612876565b63ffffffff1681526020810191909152604001600020541492915050565b6115738383836001611da6565b505050565b826000806115868484610ee1565b905061159a61159582886130c9565b611e7b565b9150848210156115c7576040516371c4efed60e01b81526004810183905260248101869052604401610c26565b50935093915050565b63ffffffff811660009081526001602052604081205480610a485760405163f6ff4fb760e01b815263ffffffff84166004820152602401610c26565b600061161e61161b8787611eb2565b90565b9050600061164a826116386116338a8a611eca565b611eed565b61164560208d018d612876565b611f22565b9050602886111561171157600061168761166a60608c0160408d016130dc565b61167760208d018d612876565b846116828c8c611f4a565b611f95565b604051633e5ac80960e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637cb59012906116dd9086908d9060009087906004016130f9565b600060405180830381600087803b1580156116f757600080fd5b505af115801561170b573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61174a60208d018d612876565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b038381166000908152600660209081526040808320938616835292905220546000198110156117ec57818110156117dd57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610c26565b6117ec84848484036000611da6565b50505050565b6001600160a01b03831661181c57604051634b637e8f60e11b815260006004820152602401610c26565b6001600160a01b0382166118465760405163ec442f0560e01b815260006004820152602401610c26565b611573838383611fc7565b6000546001600160a01b031633146110495760405163118cdaa760e01b8152336004820152602401610c26565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b606080600061193085602001356118e9866120f1565b6118f660a0890189612f7b565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061214b92505050565b9093509050600081611943576001611946565b60025b90506119666119586020880188612876565b8261085f60808a018a612f7b565b6004549093506001600160a01b031680156119ec5760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906119a9908890889060040161312a565b602060405180830381865afa1580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea919061314f565b505b5050509250929050565b60408051808201909152600080825260208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611a59896115d0565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611a8e92919061316c565b6040805180830381865afa158015611aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ace9190613215565b95945050505050565b63ffffffff81166000908152600b6020908152604080832081518083019092525461ffff8116825262010000900460ff16151591810182905290611b2157600a5461ffff16610cbe565b5192915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611c4f57611baa828281518110611b9957611b99612f44565b602002602001015160400151611c7f565b818181518110611bbc57611bbc612f44565b60200260200101516040015160036000848481518110611bde57611bde612f44565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611c1857611c18612f44565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611c469190613281565b50600101611b7b565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610db19190613340565b600281015161ffff8116600314610cd75781604051639a6d49cd60e01b8152600401610c2691906125ea565b611cb3612553565b6040805180820190915260008082526020820152600080611cea33604089013560608a0135611ce560208c018c612876565b6121c5565b91509150600080611cfb89846118d3565b9092509050611d27611d1060208b018b612876565b8383611d21368d90038d018d6133cb565b8b612218565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611d75908d018d612876565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6001600160a01b038416611dd05760405163e602df0560e01b815260006004820152602401610c26565b6001600160a01b038316611dfa57604051634a1406b160e11b815260006004820152602401610c26565b6001600160a01b03808516600090815260066020908152604080832093871683529290522082905580156117ec57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611e6d91815260200190565b60405180910390a350505050565b60007f0000000000000000000000000000000000000000000000000000000000000000611ea88184612cdd565b610a489190612cc6565b6000611ec16020828486612eb5565b610cbe916133fd565b6000611eda602860208486612eb5565b611ee39161341b565b60c01c9392505050565b6000610a487f00000000000000000000000000000000000000000000000000000000000000006001600160401b038416612cc6565b60006001600160a01b038416611f385761dead93505b611f428484612323565b509092915050565b6060611f598260288186612eb5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b606084848484604051602001611fae949392919061344b565b6040516020818303038152906040529050949350505050565b6001600160a01b038316611ff2578060076000828254611fe7919061349a565b909155506120649050565b6001600160a01b038316600090815260056020526040902054818110156120455760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610c26565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b0382166120805760078054829003905561209f565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516120e491815260200190565b60405180910390a3505050565b60008061211e7f000000000000000000000000000000000000000000000000000000000000000084612cdd565b90506001600160401b03811115610a485760405163e2ce941360e01b815260048101829052602401610c26565b805160609015158061219457848460405160200161218092919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526121bb565b848433856040516020016121ab94939291906134ad565b6040516020818303038152906040525b9150935093915050565b6000806121d3858585611578565b909250905060006121e482846130c9565b9050801561220457600c546122049088906001600160a01b0316836117f2565b61220e8783612359565b5094509492505050565b612220612553565b600061222f846000015161238f565b6020850151909150156122495761224984602001516123b7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016122998c6115d0565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016122d592919061316c565b60806040518083038185885af11580156122f3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061231891906134f0565b979650505050505050565b6001600160a01b03821661234d5760405163ec442f0560e01b815260006004820152602401610c26565b610cd760008383611fc7565b6001600160a01b03821661238357604051634b637e8f60e11b815260006004820152602401610c26565b610cd782600083611fc7565b60008134146123b3576040516304fb820960e51b8152346004820152602401610c26565b5090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243b9190612c64565b90506001600160a01b038116612464576040516329b99a9560e11b815260040160405180910390fd5b6040805133602482018190527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0381811660448501526064808501889052855180860390910181526084909401909452602080840180516001600160e01b03166323b872dd60e01b1781528451610cd79688169589936117ec93889360009283929091839182885af180612505576040513d6000823e3d81fd5b50506000513d9150811561251d57806001141561252a565b6001600160a01b0384163b155b156117ec57604051635274afe760e01b81526001600160a01b0385166004820152602401610c26565b60405180606001604052806000801916815260200160006001600160401b03168152602001612595604051806040016040528060008152602001600081525090565b905290565b60005b838110156125b557818101518382015260200161259d565b50506000910152565b600081518084526125d681602086016020860161259a565b601f01601f19169290920160200192915050565b602081526000610cbe60208301846125be565b6001600160a01b038116811461152d57600080fd5b6000806040838503121561262557600080fd5b8235612630816125fd565b946020939093013593505050565b600060e0828403121561265057600080fd5b50919050565b60006020828403121561266857600080fd5b81356001600160401b0381111561267e57600080fd5b610f1c8482850161263e565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b838110156127055788870360bf190185528151805188528301518388018790526126f2878901826125be565b97505093820193908201906001016126c6565b50508751606088015250505060208501516080850152509050610f1c565b60006060828403121561265057600080fd5b60008083601f84011261274757600080fd5b5081356001600160401b0381111561275e57600080fd5b60208301915083602082850101111561277657600080fd5b9250929050565b600080600080600080600060e0888a03121561279857600080fd5b6127a28989612723565b96506060880135955060808801356001600160401b03808211156127c557600080fd5b6127d18b838c01612735565b909750955060a08a013591506127e6826125fd565b90935060c089013590808211156127fc57600080fd5b506128098a828b01612735565b989b979a50959850939692959293505050565b60008060006060848603121561283157600080fd5b833561283c816125fd565b9250602084013561284c816125fd565b929592945050506040919091013590565b803563ffffffff8116811461287157600080fd5b919050565b60006020828403121561288857600080fd5b610cbe8261285d565b600080604083850312156128a457600080fd5b6126308361285d565b801515811461152d57600080fd5b600080604083850312156128ce57600080fd5b82356001600160401b038111156128e457600080fd5b6128f08582860161263e565b9250506020830135612901816128ad565b809150509250929050565b815181526020808301519082015260408101610a48565b803561ffff8116811461287157600080fd5b60006020828403121561294757600080fd5b610cbe82612923565b60006020828403121561296257600080fd5b8135610cbe816125fd565b6000806040838503121561298057600080fd5b6129898361285d565b915061299760208401612923565b90509250929050565b6000806000606084860312156129b557600080fd5b6129be8461285d565b92506129cc60208501612923565b915060408401356129dc816128ad565b809150509250925092565b60008060008060a085870312156129fd57600080fd5b612a078686612723565b935060608501356001600160401b03811115612a2257600080fd5b612a2e87828801612735565b9094509250506080850135612a42816125fd565b939692955090935050565b60008083601f840112612a5f57600080fd5b5081356001600160401b03811115612a7657600080fd5b6020830191508360208260051b850101111561277657600080fd5b60008060208385031215612aa457600080fd5b82356001600160401b03811115612aba57600080fd5b612ac685828601612a4d565b90969095509350505050565b60008060008060608587031215612ae857600080fd5b612af18561285d565b9350612aff60208601612923565b925060408501356001600160401b03811115612b1a57600080fd5b612b2687828801612735565b95989497509550505050565b60008060008385036080811215612b4857600080fd5b84356001600160401b03811115612b5e57600080fd5b612b6a8782880161263e565b9450506040601f1982011215612b7f57600080fd5b5060208401915060608401356129dc816125fd565b600060c082019050835182526001600160401b0360208501511660208301526040840151612bcf604084018280518252602090810151910152565b5082516080830152602083015160a0830152610cbe565b60008060408385031215612bf957600080fd5b8235612c04816125fd565b91506020830135612901816125fd565b600060608284031215612c2657600080fd5b610cbe8383612723565b600181811c90821680612c4457607f821691505b60208210810361265057634e487b7160e01b600052602260045260246000fd5b600060208284031215612c7657600080fd5b8151610cbe816125fd565b600060208284031215612c9357600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610a4857610a48612cb0565b600082612cfa57634e487b7160e01b600052601260045260246000fd5b500490565b604051606081016001600160401b0381118282101715612d2157612d21612c9a565b60405290565b604080519081016001600160401b0381118282101715612d2157612d21612c9a565b604051601f8201601f191681016001600160401b0381118282101715612d7157612d71612c9a565b604052919050565b60006001600160401b03821115612d9257612d92612c9a565b50601f01601f191660200190565b60006001600160401b0380841115612dba57612dba612c9a565b8360051b6020612dcb818301612d49565b868152918501918181019036841115612de357600080fd5b865b84811015612ea957803586811115612dfd5760008081fd5b88016060368290031215612e115760008081fd5b612e19612cff565b612e228261285d565b8152612e2f868301612923565b8682015260408083013589811115612e475760008081fd5b929092019136601f840112612e5c5760008081fd5b8235612e6f612e6a82612d79565b612d49565b8181523689838701011115612e845760008081fd5b818986018a830137600091810189019190915290820152845250918301918301612de5565b50979650505050505050565b60008085851115612ec557600080fd5b83861115612ed257600080fd5b5050820193919092039150565b60008451612ef181846020890161259a565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610f1c602083018486612f07565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112612f7157600080fd5b9190910192915050565b6000808335601e19843603018112612f9257600080fd5b8301803591506001600160401b03821115612fac57600080fd5b60200191503681900382131561277657600080fd5b6001600160401b038116811461152d57600080fd5b63ffffffff612fe48961285d565b168152602088013560208201526000604089013561300181612fc1565b6001600160401b03811660408401525087606083015260e0608083015261302c60e083018789612f07565b6001600160a01b03861660a084015282810360c084015261304e818587612f07565b9a9950505050505050505050565b60006020828403121561306e57600080fd5b81516001600160401b0381111561308457600080fd5b8201601f8101841361309557600080fd5b80516130a3612e6a82612d79565b8181528560208385010111156130b857600080fd5b611ace82602083016020860161259a565b81810381811115610a4857610a48612cb0565b6000602082840312156130ee57600080fd5b8135610cbe81612fc1565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610d3860808301846125be565b60408152600061313d60408301856125be565b8281036020840152611ace81856125be565b60006020828403121561316157600080fd5b8151610cbe816128ad565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526131a260e08401826125be565b90506060850151603f198483030160a08501526131bf82826125be565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b6000604082840312156131f757600080fd5b6131ff612d27565b9050815181526020820151602082015292915050565b60006040828403121561322757600080fd5b610cbe83836131e5565b601f821115611573576000816000526020600020601f850160051c8101602086101561325a5750805b601f850160051c820191505b8181101561327957828155600101613266565b505050505050565b81516001600160401b0381111561329a5761329a612c9a565b6132ae816132a88454612c30565b84613231565b602080601f8311600181146132e357600084156132cb5750858301515b600019600386901b1c1916600185901b178555613279565b600085815260208120601f198616915b82811015613312578886015182559484019460019091019084016132f3565b50858210156133305787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133bd57888303603f190185528151805163ffffffff1684528781015161ffff168885015286015160608785018190526133a9818601836125be565b968901969450505090860190600101613369565b509098975050505050505050565b6000604082840312156133dd57600080fd5b6133e5612d27565b82358152602083013560208201528091505092915050565b80356020831015610a4857600019602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156134435780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161348a81602c85016020870161259a565b91909101602c0195945050505050565b80820180821115610a4857610a48612cb0565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516134e081604885016020870161259a565b9190910160480195945050505050565b60006080828403121561350257600080fd5b61350a612cff565b82518152602083015161351c81612fc1565b602082015261352e84604085016131e5565b6040820152939250505056fea2646970667358221220da31c6192c431a4475e8627e64ad04324c8ba067ca5e705a81e3b2940bfe488164736f6c63430008160033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b000000000000000000000000ccae7718e4fbdfab49db96e6d7c47d825d78fa07000000000000000000000000000000000000000000000000000000000000000b577261707065642042544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045742544300000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102c95760003560e01c8063715018a611610175578063bb0b6a53116100dc578063d045a0dc11610095578063e1a452181161006f578063e1a452181461094c578063f2fde38b14610962578063fc0c546a14610569578063ff7bd03d1461098257600080fd5b8063d045a0dc146108d3578063d4243885146108e6578063dd62ed3e1461090657600080fd5b8063bb0b6a5314610817578063bc70b35414610844578063bcae25a414610864578063bd815db01461087f578063c7c7f5b314610892578063ca5eb5e1146108b357600080fd5b8063963efcaa1161012e578063963efcaa1461074f5780639f68b96414610783578063a9059cbb14610797578063b731ea0a146107b7578063b9818be1146107d7578063b98bd070146107f757600080fd5b8063715018a61461069d5780637d25a05e146106b257806382413eac146106ed578063857749b01461046a5780638da5cb5b1461071c57806395d89b411461073a57600080fd5b80633194c180116102345780635535d461116101ed5780635e280f11116101c75780635e280f11146105f35780636db7bcdb146106275780636fc1b31e1461064757806370a082311461066757600080fd5b80635535d4611461057c5780635a0dfe4d1461059c5780635bf9c226146105d357600080fd5b80633194c180146104865780633400288b146104dc5780633b6f743b146104fc5780634488b652146105295780634b104eff1461054957806352ae28791461056957600080fd5b8063156a0d0f11610286578063156a0d0f146103cd57806317442b70146103f457806318160ddd146104165780631f5e13341461043557806323b872dd1461044a578063313ce5671461046a57600080fd5b806306fdde03146102ce578063095ea7b3146102f95780630d35b41514610329578063111ecdad1461035857806313137d6514610390578063134d4f25146103a5575b600080fd5b3480156102da57600080fd5b506102e36109a2565b6040516102f091906125ea565b60405180910390f35b34801561030557600080fd5b50610319610314366004612612565b610a34565b60405190151581526020016102f0565b34801561033557600080fd5b50610349610344366004612656565b610a4e565b6040516102f09392919061268a565b34801561036457600080fd5b50600454610378906001600160a01b031681565b6040516001600160a01b0390911681526020016102f0565b6103a361039e36600461277d565b610bdf565b005b3480156103b157600080fd5b506103ba600281565b60405161ffff90911681526020016102f0565b3480156103d957600080fd5b506040805162b9270b60e21b815260016020820152016102f0565b34801561040057600080fd5b50604080516001815260026020820152016102f0565b34801561042257600080fd5b506007545b6040519081526020016102f0565b34801561044157600080fd5b506103ba600181565b34801561045657600080fd5b5061031961046536600461281c565b610c9f565b34801561047657600080fd5b50604051600881526020016102f0565b34801561049257600080fd5b506104c26104a1366004612876565b600b6020526000908152604090205461ffff81169062010000900460ff1682565b6040805161ffff90931683529015156020830152016102f0565b3480156104e857600080fd5b506103a36104f7366004612891565b610cc5565b34801561050857600080fd5b5061051c6105173660046128bb565b610cdb565b6040516102f0919061290c565b34801561053557600080fd5b506103a3610544366004612935565b610d42565b34801561055557600080fd5b506103a3610564366004612950565b610dbc565b34801561057557600080fd5b5030610378565b34801561058857600080fd5b506102e361059736600461296d565b610e3c565b3480156105a857600080fd5b506103196105b7366004612891565b63ffffffff919091166000908152600160205260409020541490565b3480156105df57600080fd5b506104276105ee366004612891565b610ee1565b3480156105ff57600080fd5b506103787f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b81565b34801561063357600080fd5b506103a36106423660046129a0565b610f24565b34801561065357600080fd5b506103a3610662366004612950565b610fe1565b34801561067357600080fd5b50610427610682366004612950565b6001600160a01b031660009081526005602052604090205490565b3480156106a957600080fd5b506103a3611037565b3480156106be57600080fd5b506106d56106cd366004612891565b600092915050565b6040516001600160401b0390911681526020016102f0565b3480156106f957600080fd5b506103196107083660046129e7565b6001600160a01b0381163014949350505050565b34801561072857600080fd5b506000546001600160a01b0316610378565b34801561074657600080fd5b506102e361104b565b34801561075b57600080fd5b506104277f000000000000000000000000000000000000000000000000000000000000000181565b34801561078f57600080fd5b506000610319565b3480156107a357600080fd5b506103196107b2366004612612565b61105a565b3480156107c357600080fd5b50600254610378906001600160a01b031681565b3480156107e357600080fd5b50600c54610378906001600160a01b031681565b34801561080357600080fd5b506103a3610812366004612a91565b611068565b34801561082357600080fd5b50610427610832366004612876565b60016020526000908152604090205481565b34801561085057600080fd5b506102e361085f366004612ad2565b611082565b34801561087057600080fd5b50600a546103ba9061ffff1681565b6103a361088d366004612a91565b61122a565b6108a56108a0366004612b32565b6113b4565b6040516102f0929190612b94565b3480156108bf57600080fd5b506103a36108ce366004612950565b6113e7565b6103a36108e136600461277d565b61146d565b3480156108f257600080fd5b506103a3610901366004612950565b61149c565b34801561091257600080fd5b50610427610921366004612be6565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b34801561095857600080fd5b506103ba61271081565b34801561096e57600080fd5b506103a361097d366004612950565b6114f2565b34801561098e57600080fd5b5061031961099d366004612c14565b611530565b6060600880546109b190612c30565b80601f01602080910402602001604051908101604052809291908181526020018280546109dd90612c30565b8015610a2a5780601f106109ff57610100808354040283529160200191610a2a565b820191906000526020600020905b815481529060010190602001808311610a0d57829003601f168201915b5050505050905090565b600033610a42818585611566565b60019150505b92915050565b60408051808201909152600080825260208201526060610a81604051806040016040528060008152602001600081525090565b600080306001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae69190612c64565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b479190612c81565b60408051808201825284815260208082018490528251600080825291810190935290975091925090610b9c565b604080518082019091526000815260606020820152815260200190600190039081610b745790505b509350600080610bc1604089013560608a0135610bbc60208c018c612876565b611578565b60408051808201909152918252602082015296989597505050505050565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163314610c2f576040516391ac5e4f60e01b81523360048201526024015b60405180910390fd5b60208701803590610c4990610c44908a612876565b6115d0565b14610c8757610c5b6020880188612876565b60405163309afaf360e21b815263ffffffff909116600482015260208801356024820152604401610c26565b610c968787878787878761160c565b50505050505050565b600033610cad858285611773565b610cb88585856117f2565b60019150505b9392505050565b610ccd611851565b610cd7828261187e565b5050565b60408051808201909152600080825260208201526000610d0b60408501356060860135610bbc6020880188612876565b915050600080610d1b86846118d3565b9092509050610d38610d306020880188612876565b8383886119f6565b9695505050505050565b610d4a611851565b61271061ffff82161115610d715760405163c6cc5d7f60e01b815260040160405180910390fd5b600a805461ffff191661ffff83169081179091556040519081527f9283ddc0c2b59320e00b0ae4a992b110df098c38e3b6ea1d92fe7a6d3504be9b906020015b60405180910390a150565b610dc4611851565b6001600160a01b038116610dee576040516001628bfb2560e01b0319815260040160405180910390fd5b600c80546001600160a01b0319166001600160a01b0383169081179091556040519081527f235247fd708c3a4799d15b30e49e97ff43e74e18a909590c0a9f257a379e19f890602001610db1565b600360209081526000928352604080842090915290825290208054610e6090612c30565b80601f0160208091040260200160405190810160405280929190818152602001828054610e8c90612c30565b8015610ed95780601f10610eae57610100808354040283529160200191610ed9565b820191906000526020600020905b815481529060010190602001808311610ebc57829003601f168201915b505050505081565b600080610eed84611ad7565b905061ffff811615610f1957612710610f0a61ffff831685612cc6565b610f149190612cdd565b610f1c565b60005b949350505050565b610f2c611851565b61271061ffff83161115610f535760405163c6cc5d7f60e01b815260040160405180910390fd5b60408051808201825261ffff848116808352841515602080850182815263ffffffff8a166000818152600b84528890209651875492511515620100000262ffffff1990931696169590951717909455845192835292820152918201527f56f0bca120766dba5aeeb89a1cf629c3495dc497c82f426d4e4d58c54b72764c9060600160405180910390a1505050565b610fe9611851565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527ff0be4f1e87349231d80c36b33f9e8639658eeaf474014dee15a3e6a4d441419790602001610db1565b61103f611851565b6110496000611b28565b565b6060600980546109b190612c30565b600033610a428185856117f2565b611070611851565b610cd761107d8284612da0565b611b78565b63ffffffff8416600090815260036020908152604080832061ffff871684529091528120805460609291906110b690612c30565b80601f01602080910402602001604051908101604052809291908181526020018280546110e290612c30565b801561112f5780601f106111045761010080835404028352916020019161112f565b820191906000526020600020905b81548152906001019060200180831161111257829003601f168201915b50505050509050805160000361117f5783838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929450610f1c9350505050565b600083900361118f579050610f1c565b6002831061120d576111d684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c7f92505050565b806111e48460028188612eb5565b6040516020016111f693929190612edf565b604051602081830303815290604052915050610f1c565b8383604051639a6d49cd60e01b8152600401610c26929190612f30565b60005b81811015611333573683838381811061124857611248612f44565b905060200281019061125a9190612f5a565b905061128d61126c6020830183612876565b602083013563ffffffff919091166000908152600160205260409020541490565b611297575061132b565b3063d045a0dc60c08301358360a08101356112b6610100830183612f7b565b6112c7610100890160e08a01612950565b6112d56101208a018a612f7b565b6040518963ffffffff1660e01b81526004016112f79796959493929190612fd6565b6000604051808303818588803b15801561131057600080fd5b505af1158015611324573d6000803e3d6000fd5b5050505050505b60010161122d565b50336001600160a01b0316638e9e70996040518163ffffffff1660e01b8152600401600060405180830381865afa158015611372573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261139a919081019061305c565b604051638351eea760e01b8152600401610c2691906125ea565b6113bc612553565b60408051808201909152600080825260208201526113db858585611cab565b91509150935093915050565b6113ef611851565b60405163ca5eb5e160e01b81526001600160a01b0382811660048301527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b169063ca5eb5e190602401600060405180830381600087803b15801561145257600080fd5b505af1158015611466573d6000803e3d6000fd5b5050505050565b33301461148d5760405163029a949d60e31b815260040160405180910390fd5b610c9687878787878787610c87565b6114a4611851565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fd48d879cef83a1c0bdda516f27b13ddb1b3f8bbac1c9e1511bb2a659c242776090602001610db1565b6114fa611851565b6001600160a01b03811661152457604051631e4fbdf760e01b815260006004820152602401610c26565b61152d81611b28565b50565b60006020820180359060019083906115489086612876565b63ffffffff1681526020810191909152604001600020541492915050565b6115738383836001611da6565b505050565b826000806115868484610ee1565b905061159a61159582886130c9565b611e7b565b9150848210156115c7576040516371c4efed60e01b81526004810183905260248101869052604401610c26565b50935093915050565b63ffffffff811660009081526001602052604081205480610a485760405163f6ff4fb760e01b815263ffffffff84166004820152602401610c26565b600061161e61161b8787611eb2565b90565b9050600061164a826116386116338a8a611eca565b611eed565b61164560208d018d612876565b611f22565b9050602886111561171157600061168761166a60608c0160408d016130dc565b61167760208d018d612876565b846116828c8c611f4a565b611f95565b604051633e5ac80960e11b81529091506001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b1690637cb59012906116dd9086908d9060009087906004016130f9565b600060405180830381600087803b1580156116f757600080fd5b505af115801561170b573d6000803e3d6000fd5b50505050505b6001600160a01b038216887fefed6d3500546b29533b128a29e3a94d70788727f0507505ac12eaf2e578fd9c61174a60208d018d612876565b6040805163ffffffff9092168252602082018690520160405180910390a3505050505050505050565b6001600160a01b038381166000908152600660209081526040808320938616835292905220546000198110156117ec57818110156117dd57604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610c26565b6117ec84848484036000611da6565b50505050565b6001600160a01b03831661181c57604051634b637e8f60e11b815260006004820152602401610c26565b6001600160a01b0382166118465760405163ec442f0560e01b815260006004820152602401610c26565b611573838383611fc7565b6000546001600160a01b031633146110495760405163118cdaa760e01b8152336004820152602401610c26565b63ffffffff8216600081815260016020908152604091829020849055815192835282018390527f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b910160405180910390a15050565b606080600061193085602001356118e9866120f1565b6118f660a0890189612f7b565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061214b92505050565b9093509050600081611943576001611946565b60025b90506119666119586020880188612876565b8261085f60808a018a612f7b565b6004549093506001600160a01b031680156119ec5760405163043a78eb60e01b81526001600160a01b0382169063043a78eb906119a9908890889060040161312a565b602060405180830381865afa1580156119c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ea919061314f565b505b5050509250929050565b60408051808201909152600080825260208201527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663ddc28c586040518060a001604052808863ffffffff168152602001611a59896115d0565b8152602001878152602001868152602001851515815250306040518363ffffffff1660e01b8152600401611a8e92919061316c565b6040805180830381865afa158015611aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ace9190613215565b95945050505050565b63ffffffff81166000908152600b6020908152604080832081518083019092525461ffff8116825262010000900460ff16151591810182905290611b2157600a5461ffff16610cbe565b5192915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60005b8151811015611c4f57611baa828281518110611b9957611b99612f44565b602002602001015160400151611c7f565b818181518110611bbc57611bbc612f44565b60200260200101516040015160036000848481518110611bde57611bde612f44565b60200260200101516000015163ffffffff1663ffffffff1681526020019081526020016000206000848481518110611c1857611c18612f44565b60200260200101516020015161ffff1661ffff1681526020019081526020016000209081611c469190613281565b50600101611b7b565b507fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b67481604051610db19190613340565b600281015161ffff8116600314610cd75781604051639a6d49cd60e01b8152600401610c2691906125ea565b611cb3612553565b6040805180820190915260008082526020820152600080611cea33604089013560608a0135611ce560208c018c612876565b6121c5565b91509150600080611cfb89846118d3565b9092509050611d27611d1060208b018b612876565b8383611d21368d90038d018d6133cb565b8b612218565b60408051808201909152858152602080820186905282519298509096503391907f85496b760a4b7f8d66384b9df21b381f5d1b1e79f229a47aaf4c232edc2fe59a90611d75908d018d612876565b6040805163ffffffff909216825260208201899052810187905260600160405180910390a350505050935093915050565b6001600160a01b038416611dd05760405163e602df0560e01b815260006004820152602401610c26565b6001600160a01b038316611dfa57604051634a1406b160e11b815260006004820152602401610c26565b6001600160a01b03808516600090815260066020908152604080832093871683529290522082905580156117ec57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611e6d91815260200190565b60405180910390a350505050565b60007f0000000000000000000000000000000000000000000000000000000000000001611ea88184612cdd565b610a489190612cc6565b6000611ec16020828486612eb5565b610cbe916133fd565b6000611eda602860208486612eb5565b611ee39161341b565b60c01c9392505050565b6000610a487f00000000000000000000000000000000000000000000000000000000000000016001600160401b038416612cc6565b60006001600160a01b038416611f385761dead93505b611f428484612323565b509092915050565b6060611f598260288186612eb5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929695505050505050565b606084848484604051602001611fae949392919061344b565b6040516020818303038152906040529050949350505050565b6001600160a01b038316611ff2578060076000828254611fe7919061349a565b909155506120649050565b6001600160a01b038316600090815260056020526040902054818110156120455760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610c26565b6001600160a01b03841660009081526005602052604090209082900390555b6001600160a01b0382166120805760078054829003905561209f565b6001600160a01b03821660009081526005602052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516120e491815260200190565b60405180910390a3505050565b60008061211e7f000000000000000000000000000000000000000000000000000000000000000184612cdd565b90506001600160401b03811115610a485760405163e2ce941360e01b815260048101829052602401610c26565b805160609015158061219457848460405160200161218092919091825260c01b6001600160c01b031916602082015260280190565b6040516020818303038152906040526121bb565b848433856040516020016121ab94939291906134ad565b6040516020818303038152906040525b9150935093915050565b6000806121d3858585611578565b909250905060006121e482846130c9565b9050801561220457600c546122049088906001600160a01b0316836117f2565b61220e8783612359565b5094509492505050565b612220612553565b600061222f846000015161238f565b6020850151909150156122495761224984602001516123b7565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316632637a450826040518060a001604052808b63ffffffff1681526020016122998c6115d0565b81526020018a815260200189815260200160008960200151111515815250866040518463ffffffff1660e01b81526004016122d592919061316c565b60806040518083038185885af11580156122f3573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061231891906134f0565b979650505050505050565b6001600160a01b03821661234d5760405163ec442f0560e01b815260006004820152602401610c26565b610cd760008383611fc7565b6001600160a01b03821661238357604051634b637e8f60e11b815260006004820152602401610c26565b610cd782600083611fc7565b60008134146123b3576040516304fb820960e51b8152346004820152602401610c26565b5090565b60007f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031663e4fe1d946040518163ffffffff1660e01b8152600401602060405180830381865afa158015612417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243b9190612c64565b90506001600160a01b038116612464576040516329b99a9560e11b815260040160405180910390fd5b6040805133602482018190527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0381811660448501526064808501889052855180860390910181526084909401909452602080840180516001600160e01b03166323b872dd60e01b1781528451610cd79688169589936117ec93889360009283929091839182885af180612505576040513d6000823e3d81fd5b50506000513d9150811561251d57806001141561252a565b6001600160a01b0384163b155b156117ec57604051635274afe760e01b81526001600160a01b0385166004820152602401610c26565b60405180606001604052806000801916815260200160006001600160401b03168152602001612595604051806040016040528060008152602001600081525090565b905290565b60005b838110156125b557818101518382015260200161259d565b50506000910152565b600081518084526125d681602086016020860161259a565b601f01601f19169290920160200192915050565b602081526000610cbe60208301846125be565b6001600160a01b038116811461152d57600080fd5b6000806040838503121561262557600080fd5b8235612630816125fd565b946020939093013593505050565b600060e0828403121561265057600080fd5b50919050565b60006020828403121561266857600080fd5b81356001600160401b0381111561267e57600080fd5b610f1c8482850161263e565b8351815260208085015190820152600060a08201604060a0604085015281865180845260c08601915060c08160051b8701019350602080890160005b838110156127055788870360bf190185528151805188528301518388018790526126f2878901826125be565b97505093820193908201906001016126c6565b50508751606088015250505060208501516080850152509050610f1c565b60006060828403121561265057600080fd5b60008083601f84011261274757600080fd5b5081356001600160401b0381111561275e57600080fd5b60208301915083602082850101111561277657600080fd5b9250929050565b600080600080600080600060e0888a03121561279857600080fd5b6127a28989612723565b96506060880135955060808801356001600160401b03808211156127c557600080fd5b6127d18b838c01612735565b909750955060a08a013591506127e6826125fd565b90935060c089013590808211156127fc57600080fd5b506128098a828b01612735565b989b979a50959850939692959293505050565b60008060006060848603121561283157600080fd5b833561283c816125fd565b9250602084013561284c816125fd565b929592945050506040919091013590565b803563ffffffff8116811461287157600080fd5b919050565b60006020828403121561288857600080fd5b610cbe8261285d565b600080604083850312156128a457600080fd5b6126308361285d565b801515811461152d57600080fd5b600080604083850312156128ce57600080fd5b82356001600160401b038111156128e457600080fd5b6128f08582860161263e565b9250506020830135612901816128ad565b809150509250929050565b815181526020808301519082015260408101610a48565b803561ffff8116811461287157600080fd5b60006020828403121561294757600080fd5b610cbe82612923565b60006020828403121561296257600080fd5b8135610cbe816125fd565b6000806040838503121561298057600080fd5b6129898361285d565b915061299760208401612923565b90509250929050565b6000806000606084860312156129b557600080fd5b6129be8461285d565b92506129cc60208501612923565b915060408401356129dc816128ad565b809150509250925092565b60008060008060a085870312156129fd57600080fd5b612a078686612723565b935060608501356001600160401b03811115612a2257600080fd5b612a2e87828801612735565b9094509250506080850135612a42816125fd565b939692955090935050565b60008083601f840112612a5f57600080fd5b5081356001600160401b03811115612a7657600080fd5b6020830191508360208260051b850101111561277657600080fd5b60008060208385031215612aa457600080fd5b82356001600160401b03811115612aba57600080fd5b612ac685828601612a4d565b90969095509350505050565b60008060008060608587031215612ae857600080fd5b612af18561285d565b9350612aff60208601612923565b925060408501356001600160401b03811115612b1a57600080fd5b612b2687828801612735565b95989497509550505050565b60008060008385036080811215612b4857600080fd5b84356001600160401b03811115612b5e57600080fd5b612b6a8782880161263e565b9450506040601f1982011215612b7f57600080fd5b5060208401915060608401356129dc816125fd565b600060c082019050835182526001600160401b0360208501511660208301526040840151612bcf604084018280518252602090810151910152565b5082516080830152602083015160a0830152610cbe565b60008060408385031215612bf957600080fd5b8235612c04816125fd565b91506020830135612901816125fd565b600060608284031215612c2657600080fd5b610cbe8383612723565b600181811c90821680612c4457607f821691505b60208210810361265057634e487b7160e01b600052602260045260246000fd5b600060208284031215612c7657600080fd5b8151610cbe816125fd565b600060208284031215612c9357600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610a4857610a48612cb0565b600082612cfa57634e487b7160e01b600052601260045260246000fd5b500490565b604051606081016001600160401b0381118282101715612d2157612d21612c9a565b60405290565b604080519081016001600160401b0381118282101715612d2157612d21612c9a565b604051601f8201601f191681016001600160401b0381118282101715612d7157612d71612c9a565b604052919050565b60006001600160401b03821115612d9257612d92612c9a565b50601f01601f191660200190565b60006001600160401b0380841115612dba57612dba612c9a565b8360051b6020612dcb818301612d49565b868152918501918181019036841115612de357600080fd5b865b84811015612ea957803586811115612dfd5760008081fd5b88016060368290031215612e115760008081fd5b612e19612cff565b612e228261285d565b8152612e2f868301612923565b8682015260408083013589811115612e475760008081fd5b929092019136601f840112612e5c5760008081fd5b8235612e6f612e6a82612d79565b612d49565b8181523689838701011115612e845760008081fd5b818986018a830137600091810189019190915290820152845250918301918301612de5565b50979650505050505050565b60008085851115612ec557600080fd5b83861115612ed257600080fd5b5050820193919092039150565b60008451612ef181846020890161259a565b8201838582376000930192835250909392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000610f1c602083018486612f07565b634e487b7160e01b600052603260045260246000fd5b6000823561013e19833603018112612f7157600080fd5b9190910192915050565b6000808335601e19843603018112612f9257600080fd5b8301803591506001600160401b03821115612fac57600080fd5b60200191503681900382131561277657600080fd5b6001600160401b038116811461152d57600080fd5b63ffffffff612fe48961285d565b168152602088013560208201526000604089013561300181612fc1565b6001600160401b03811660408401525087606083015260e0608083015261302c60e083018789612f07565b6001600160a01b03861660a084015282810360c084015261304e818587612f07565b9a9950505050505050505050565b60006020828403121561306e57600080fd5b81516001600160401b0381111561308457600080fd5b8201601f8101841361309557600080fd5b80516130a3612e6a82612d79565b8181528560208385010111156130b857600080fd5b611ace82602083016020860161259a565b81810381811115610a4857610a48612cb0565b6000602082840312156130ee57600080fd5b8135610cbe81612fc1565b60018060a01b038516815283602082015261ffff83166040820152608060608201526000610d3860808301846125be565b60408152600061313d60408301856125be565b8281036020840152611ace81856125be565b60006020828403121561316157600080fd5b8151610cbe816128ad565b6040815263ffffffff8351166040820152602083015160608201526000604084015160a060808401526131a260e08401826125be565b90506060850151603f198483030160a08501526131bf82826125be565b60809690960151151560c08501525050506001600160a01b039190911660209091015290565b6000604082840312156131f757600080fd5b6131ff612d27565b9050815181526020820151602082015292915050565b60006040828403121561322757600080fd5b610cbe83836131e5565b601f821115611573576000816000526020600020601f850160051c8101602086101561325a5750805b601f850160051c820191505b8181101561327957828155600101613266565b505050505050565b81516001600160401b0381111561329a5761329a612c9a565b6132ae816132a88454612c30565b84613231565b602080601f8311600181146132e357600084156132cb5750858301515b600019600386901b1c1916600185901b178555613279565b600085815260208120601f198616915b82811015613312578886015182559484019460019091019084016132f3565b50858210156133305787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133bd57888303603f190185528151805163ffffffff1684528781015161ffff168885015286015160608785018190526133a9818601836125be565b968901969450505090860190600101613369565b509098975050505050505050565b6000604082840312156133dd57600080fd5b6133e5612d27565b82358152602083013560208201528091505092915050565b80356020831015610a4857600019602084900360031b1b1692915050565b6001600160c01b031981358181169160088510156134435780818660080360031b1b83161692505b505092915050565b6001600160401b0360c01b8560c01b16815263ffffffff60e01b8460e01b16600882015282600c8201526000825161348a81602c85016020870161259a565b91909101602c0195945050505050565b80820180821115610a4857610a48612cb0565b8481526001600160401b0360c01b8460c01b166020820152826028820152600082516134e081604885016020870161259a565b9190910160480195945050505050565b60006080828403121561350257600080fd5b61350a612cff565b82518152602083015161351c81612fc1565b602082015261352e84604085016131e5565b6040820152939250505056fea2646970667358221220da31c6192c431a4475e8627e64ad04324c8ba067ca5e705a81e3b2940bfe488164736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b000000000000000000000000ccae7718e4fbdfab49db96e6d7c47d825d78fa07000000000000000000000000000000000000000000000000000000000000000b577261707065642042544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045742544300000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Wrapped BTC
Arg [1] : _symbol (string): WBTC
Arg [2] : _lzEndpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
Arg [3] : _owner (address): 0xccaE7718e4fbdfaB49dB96E6D7c47D825D78fa07
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Arg [3] : 000000000000000000000000ccae7718e4fbdfab49db96e6d7c47d825d78fa07
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [5] : 5772617070656420425443000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [7] : 5742544300000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
99:394:45:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89:38;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3979:186;;;;;;;;;;-1:-1:-1;3979:186:38;;;;;:::i;:::-;;:::i;:::-;;;1391:14:46;;1384:22;1366:41;;1354:2;1339:18;3979:186:38;1226:187:46;5176:1276:27;;;;;;;;;;-1:-1:-1;5176:1276:27;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;2330:27::-;;;;;;;;;;-1:-1:-1;2330:27:27;;;;-1:-1:-1;;;;;2330:27:27;;;;;;-1:-1:-1;;;;;3605:32:46;;;3587:51;;3575:2;3560:18;2330:27:27;3441:203:46;4368:708:12;;;;;;:::i;:::-;;:::i;:::-;;2204:40:27;;;;;;;;;;;;2243:1;2204:40;;;;;5385:6:46;5373:19;;;5355:38;;5343:2;5328:18;2204:40:27;5211:188:46;3475:140:27;;;;;;;;;;-1:-1:-1;3475:140:27;;;-1:-1:-1;;;5574:52:46;;3606:1:27;5657:2:46;5642:18;;5635:59;5547:18;3475:140:27;5404:296:46;1287:235:10;;;;;;;;;;-1:-1:-1;1287:235:10;;;843:1:13;5912:34:46;;678:1:12;5977:2:46;5962:18;;5955:43;5848:18;1287:235:10;5705:299:46;2830:97:38;;;;;;;;;;-1:-1:-1;2908:12:38;;2830:97;;;6155:25:46;;;6143:2;6128:18;2830:97:38;6009:177:46;2167:31:27;;;;;;;;;;;;2197:1;2167:31;;4757:244:38;;;;;;;;;;-1:-1:-1;4757:244:38;;;;;:::i;:::-;;:::i;315:82:45:-;;;;;;;;;;-1:-1:-1;315:82:45;;389:1;6794:36:46;;6782:2;6767:18;315:82:45;6652:184:46;577:56:23;;;;;;;;;;-1:-1:-1;577:56:23;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;7394:6:46;7382:19;;;7364:38;;7445:14;;7438:22;7433:2;7418:18;;7411:50;7337:18;577:56:23;7198:269:46;1724:108:11;;;;;;;;;;-1:-1:-1;1724:108:11;;;;;:::i;:::-;;:::i;6903:774:27:-;;;;;;;;;;-1:-1:-1;6903:774:27;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;730:206:23:-;;;;;;;;;;-1:-1:-1;730:206:23;;;;;:::i;:::-;;:::i;663:196:44:-;;;;;;;;;;-1:-1:-1;663:196:44;;;;;:::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:27:-;;;;;;;;;;-1:-1:-1;16151:132:27;;;;;:::i;:::-;16256:11;;;;;16233:4;16256:11;;;:5;:11;;;;;;:20;;16151:132;1421:201:23;;;;;;;;;;-1:-1:-1;1421:201:23;;;;;:::i;:::-;;:::i;446:46:11:-;;;;;;;;;;;;;;;1054:265:23;;;;;;;;;;-1:-1:-1;1054:265:23;;;;;:::i;:::-;;:::i;4657:163:27:-;;;;;;;;;;-1:-1:-1;4657:163:27;;;;;:::i;:::-;;:::i;2985:116:38:-;;;;;;;;;;-1:-1:-1;2985:116:38;;;;;:::i;:::-;-1:-1:-1;;;;;3076:18:38;3050:7;3076:18;;;:9;:18;;;;;;;2985:116;2293:101:33;;;;;;;;;;;;;:::i;3507:128:12:-;;;;;;;;;;-1:-1:-1;3507:128:12;;;;;:::i;:::-;3596:12;3507:128;;;;;;;;-1:-1:-1;;;;;10738:31:46;;;10720:50;;10708:2;10693:18;3507:128:12;10576:200:46;2013:216:12;;;;;;;;;;-1:-1:-1;2013:216:12;;;;;:::i;:::-;-1:-1:-1;;;;;2198:24:12;;2217:4;2198:24;2013:216;;;;;;;1638:85:33;;;;;;;;;;-1:-1:-1;1684:7:33;1710:6;-1:-1:-1;;;;;1710:6:33;1638:85;;1962:93:38;;;;;;;;;;;;;:::i;1861:46:27:-;;;;;;;;;;;;;;;1460:94:25;;;;;;;;;;-1:-1:-1;1519:4:25;1460:94;;3296:178:38;;;;;;;;;;-1:-1:-1;3296:178:38;;;;;:::i;:::-;;:::i;559:23:19:-;;;;;;;;;;-1:-1:-1;559:23:19;;;;-1:-1:-1;;;;;559:23:19;;;362::44;;;;;;;;;;-1:-1:-1;362:23:44;;;;-1:-1:-1;;;;;362:23:44;;;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;447:27:23:-;;;;;;;;;;-1:-1:-1;447:27:23;;;;;;;;1698:1333:19;;;;;;:::i;:::-;;:::i;8365:290:27:-;;;;;;:::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:38:-;;;;;;;;;;-1:-1:-1;3532:140:38;;;;;:::i;:::-;-1:-1:-1;;;;;3638:18:38;;;3612:7;3638:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3532:140;312:47:23;;;;;;;;;;;;353:6;312:47;;2543:215:33;;;;;;;;;;-1:-1:-1;2543:215:33;;;;;:::i;:::-;;:::i;2771:149:12:-;;;;;;;;;;-1:-1:-1;2771:149:12;;;;;:::i;:::-;;:::i;1760:89:38:-;1805:13;1837:5;1830:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89;:::o;3979:186::-;4052:4;735:10:42;4106:31:38;735:10:42;4122:7:38;4131:5;4106:8;:31::i;:::-;4154:4;4147:11;;;3979:186;;;;;:::o;5176:1276:27:-;-1:-1:-1;;;;;;;;;;;;;;;;;5328:35:27;5365:28;-1:-1:-1;;;;;;;;;;;;;;;;;;;5365:28:27;5409:19;5483;5512:4;-1:-1:-1;;;;;5512:10:27;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5505:32:27;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5601;;;;;;;;;;;;;;;;;;5752:21;;-1:-1:-1;5752:21:27;;;;;;;;;5601:34;;-1:-1:-1;5601:34:27;;-1:-1:-1;5752:21:27;;;;-1:-1:-1;;;;;;;;;;;;;;;;;5752:21:27;;;;;;;;;;;;;;;-1:-1:-1;5736:37:27;-1:-1:-1;6210:20:27;;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:27: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;;;3587:51:46;3560: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;;16676:10:46;16664:23;;;4896:40:12;;;16646:42:46;4921:14:12;;;;16704:18:46;;;16697:34;16619:18;;4896:40:12;16474:263:46;4833:103:12;5010:59;5021:7;5030:5;5037:8;;5047:9;5058:10;;5010;:59::i;:::-;4368:708;;;;;;;:::o;4757:244:38:-;4844:4;735:10:42;4900:37:38;4916:4;735:10:42;4931:5:38;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:33;:11;:13::i;:::-;1804:21:11::1;1813:4;1819:5;1804:8;:21::i;:::-;1724:108:::0;;:::o;6903:774:27:-;-1:-1:-1;;;;;;;;;;;;;;;;;7237:24:27;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:27;-1:-1:-1;7612:58:27;7619:17;;;;:10;:17;:::i;:::-;7638:7;7647;7656:13;7612:6;:58::i;:::-;7605:65;6903:774;-1:-1:-1;;;;;;6903:774:27:o;730:206:23:-;1531:13:33;:11;:13::i;:::-;353:6:23::1;805:25;::::0;::::1;;801:55;;;839:17;;-1:-1:-1::0;;;839:17:23::1;;;;;;;;;;;801:55;866:13;:23:::0;;-1:-1:-1;;866:23:23::1;;::::0;::::1;::::0;;::::1;::::0;;;904:25:::1;::::0;5355:38:46;;;904:25:23::1;::::0;5343:2:46;5328:18;904:25:23::1;;;;;;;;730:206:::0;:::o;663:196:44:-;1531:13:33;:11;:13::i;:::-;-1:-1:-1;;;;;736:23:44;::::1;732:53;;768:17;;-1:-1:-1::0;;;;;;768:17:44::1;;;;;;;;;;;732:53;795:8;:20:::0;;-1:-1:-1;;;;;;795:20:44::1;-1:-1:-1::0;;;;;795:20:44;::::1;::::0;;::::1;::::0;;;830:22:::1;::::0;3587:51:46;;;830:22:44::1;::::0;3575:2:46;3560:18;830:22:44::1;3441:203:46::0;538:93:18;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1421:201:23:-;1499:7;1518:10;1531:19;1542:7;1531:10;:19::i;:::-;1518:32;-1:-1:-1;1567:8:23;;;;:48;;353:6;1583:13;1582:33;1583:13;;:7;:13;:::i;:::-;1582:33;;;;:::i;:::-;1567:48;;;1578:1;1567:48;1560:55;1421:201;-1:-1:-1;;;;1421:201:23:o;1054:265::-;1531:13:33;:11;:13::i;:::-;353:6:23::1;1153:25;::::0;::::1;;1149:55;;;1187:17;;-1:-1:-1::0;;;1187:17:23::1;;;;;;;;;;;1149:55;1232:28;::::0;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;1214:15:::1;::::0;::::1;-1:-1:-1::0;1214:15:23;;;:6:::1;:15:::0;;;;;:46;;;;;;::::1;;::::0;::::1;-1:-1:-1::0;;1214:46:23;;;;::::1;::::0;;;;::::1;::::0;;;1275:37;;17461:42:46;;;17519:18;;;17512:47;17575:18;;;17568:50;1275:37:23::1;::::0;17449:2:46;17434:18;1275:37:23::1;;;;;;;1054:265:::0;;;:::o;4657:163:27:-;1531:13:33;:11;:13::i;:::-;4740:12:27::1;:28:::0;;-1:-1:-1;;;;;;4740:28:27::1;-1:-1:-1::0;;;;;4740:28:27;::::1;::::0;;::::1;::::0;;;4783:30:::1;::::0;3587:51:46;;;4783:30:27::1;::::0;3575:2:46;3560:18;4783:30:27::1;3441:203:46::0;2293:101:33;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;1962:93:38:-;2009:13;2041:7;2034:14;;;;;:::i;3296:178::-;3365:4;735:10:42;3419:27:38;735:10:42;3436:2:38;3440:5;3419:9;:27::i;1391:156:18:-;1531:13:33;: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:27;;;;;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:27:-;8526:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;8609:39:27;8615:10;8627:4;8633:14;8609:5;:39::i;:::-;8602:46;;;;8365:290;;;;;;:::o;3252:105:11:-;1531:13:33;:11;:13::i;:::-;3319:31:11::1;::::0;-1:-1:-1;;;3319:31:11;;-1:-1:-1;;;;;3605:32:46;;;3319:31:11::1;::::0;::::1;3587:51:46::0;3319:8:11::1;:20;::::0;::::1;::::0;3560:18:46;;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:33;: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;3587:51:46;;;1210:22:19::1;::::0;3575:2:46;3560:18;1210:22:19::1;3441:203:46::0;2543:215:33;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:33;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:33;;2700:1:::1;2672:31;::::0;::::1;3587:51:46::0;3560:18;;2672:31:33::1;3441:203:46::0;2623:91:33::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:38:-;8791:37;8800:5;8807:7;8816:5;8823:4;8791:8;:37::i;:::-;8707:128;;;:::o;865:657:44:-;1085:9;1012:20;;1269:26;1276:7;1085:9;1269:6;:26::i;:::-;1255:40;-1:-1:-1;1324:28:44;1336:15;1255:40;1336:9;:15;:::i;:::-;1324:11;:28::i;:::-;1305:47;;1422:12;1403:16;:31;1399:117;;;1457:48;;-1:-1:-1;;;1457:48:44;;;;;25159:25:46;;;25200:18;;;25193:34;;;25132:18;;1457:48:44;24985:248:46;1399:117:44;1060:462;865:657;;;;;;:::o;2718:196:11:-;2822:11;;;2788:7;2822:11;;;:5;:11;;;;;;;2843:43;;2874:12;;-1:-1:-1;;;2874:12:11;;25412:10:46;25400:23;;2874:12:11;;;25382:42:46;25355:18;;2874:12:11;25238:192:46;12944:1806:27;13421:17;13441:36;:17;:8;;:15;:17::i;:::-;2891:2:32;2780:123;13441:36:27;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:32;-1:-1:-1;;13710:955:27;;;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:27;;13814:201;;-1:-1:-1;;;;;;14562:8:27;:20;;;;:92;;14583:9;;14594:5;;14601:1;;13814:201;;14562:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13737:928;13710:955;-1:-1:-1;;;;;14680:63:27;;14692:5;14680:63;14699:14;;;;:7;:14;:::i;:::-;14680:63;;;16676:10:46;16664:23;;;16646:42;;16719:2;16704:18;;16697:34;;;16619:18;14680:63:27;;;;;;;13247:1503;;12944:1806;;;;;;;:::o;10396:476:38:-;-1:-1:-1;;;;;3638:18:38;;;10495:24;3638:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;10561:36:38;;10557:309;;;10636:5;10617:16;:24;10613:130;;;10668:60;;-1:-1:-1;;;10668:60:38;;-1:-1:-1;;;;;26657:32:46;;10668:60:38;;;26639:51:46;26706:18;;;26699:34;;;26749:18;;;26742:34;;;26612:18;;10668:60:38;26437:345:46;10613:130:38;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:38;;5453:86;;5498:30;;-1:-1:-1;;;5498:30:38;;5525:1;5498:30;;;3587:51:46;3560:18;;5498:30:38;3441:203:46;5453:86:38;-1:-1:-1;;;;;5552:16:38;;5548:86;;5591:32;;-1:-1:-1;;;5591:32:38;;5620:1;5591:32;;;3587:51:46;3560:18;;5591:32:38;3441:203:46;5548:86:38;5643:24;5651:4;5657:2;5661:5;5643:7;:24::i;1796:162:33:-;1684:7;1710:6;-1:-1:-1;;;;;1710:6:33;735:10:42;1855:23:33;1851:101;;1901:40;;-1:-1:-1;;;1901:40:33;;735:10:42;1901:40:33;;;3587:51:46;3560:18;;1901:40:33;3441:203:46;2286:134:11;2359:11;;;;;;;:5;:11;;;;;;;;;:19;;;2393:20;;16646:42:46;;;16704:18;;16697:34;;;2393:20:11;;16619:18:46;2393:20:11;;;;;;;2286:134;;:::o;10990:1436:27:-;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:27;;-1:-1:-1;;;11347:324:27:i;:::-;11323:348;;-1:-1:-1;11323:348:27;-1:-1:-1;11751:14:27;11323:348;11768:33;;2197:1;11768:33;;;2243:1;11768:33;11751:50;-1:-1:-1;11923:67:27;11938:17;;;;:10;:17;:::i;:::-;11957:7;11966:23;;;;:10;:23;:::i;11923:67::-;12248:12;;11913:77;;-1:-1:-1;;;;;;12248:12:27;12340:23;;12336:83;;12365:54;;-1:-1:-1;;;12365:54:27;;-1:-1:-1;;;;;12365:36:27;;;;;: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;1628:188:23:-;1731:15;;;1687:6;1731:15;;;:6;:15;;;;;;;;1705:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;1763:46;;1796:13;;;;1763:46;;;1780:13;;1756:53;-1:-1:-1;;1628:188:23:o;2912:187:33:-;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:33;;;-1:-1:-1;;;;;;3020:17:33;;;;;;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:27:-;9517:34;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;9915:20:27;;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:27;-1:-1:-1;10412:66:27;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:27;;-1:-1:-1;10646:10:27;;10610:15;10602:87;;10627:17;;;;:10;:17;:::i;:::-;10602:87;;;32803:10:46;32791:23;;;32773:42;;32846:2;32831:18;;32824:34;;;32874:18;;32867:34;;;32761:2;32746:18;10602:87:27;;;;;;;9583:1113;;;;9363:1333;;;;;;:::o;9682:432:38:-;-1:-1:-1;;;;;9794:19:38;;9790:89;;9836:32;;-1:-1:-1;;;9836:32:38;;9865:1;9836:32;;;3587:51:46;3560:18;;9836:32:38;3441:203:46;9790:89:38;-1:-1:-1;;;;;9892:21:38;;9888:90;;9936:31;;-1:-1:-1;;;9936:31:38;;9964:1;9936:31;;;3587:51:46;3560:18;;9936:31:38;3441:203:46;9888:90:38;-1:-1:-1;;;;;9987:18:38;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;10032:76;;;;10082:7;-1:-1:-1;;;;;10066:31:38;10075:5;-1:-1:-1;;;;;10066:31:38;;10091:5;10066:31;;;;6155:25:46;;6143:2;6128:18;;6009:177;10066:31:38;;;;;;;;9682:432;;;;:::o;16677:172:27:-;16748:16;16821:21;16784:33;16821:21;16784:9;:33;:::i;:::-;16783:59;;;;:::i;1573:123:32:-;1633:7;1667:21;188:2;1633:7;1667:4;;:21;:::i;:::-;1659:30;;;:::i;1874:152::-;1936:6;1975:42;243:2;188;1975:4;;:42;:::i;:::-;1968:50;;;:::i;:::-;1961:58;;;1874:152;-1:-1:-1;;;1874:152:32:o;17073:139:27:-;17137:16;17172:33;17184:21;-1:-1:-1;;;;;17172:33:27;;;:::i;2939:462:25:-;3073:24;-1:-1:-1;;;;;3113:19:25;;3109:46;;3148:6;3134:21;;3109:46;3251:21;3257:3;3262:9;3251:5;:21::i;:::-;-1:-1:-1;3385:9:25;;2939:462;-1:-1:-1;;2939:462:25:o;2186:130:32:-;2250:12;2281:28;:4;243:2;2281:4;;:28;:::i;:::-;2274:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2274:35:32;;2186:130;-1:-1:-1;;;;;;2186:130:32:o;640:284:31:-;824:17;877:6;885:7;894:9;905:11;860:57;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;853:64;;640:284;;;;;;:::o;5989:1107:38:-;-1:-1:-1;;;;;6078:18:38;;6074:540;;6230:5;6214:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;6074:540:38;;-1:-1:-1;6074:540:38;;-1:-1:-1;;;;;6288:15:38;;6266:19;6288:15;;;:9;:15;;;;;;6321:19;;;6317:115;;;6367:50;;-1:-1:-1;;;6367:50:38;;-1:-1:-1;;;;;26657:32:46;;6367:50:38;;;26639:51:46;26706:18;;;26699:34;;;26749:18;;;26742:34;;;26612:18;;6367:50:38;26437:345:46;6317:115:38;-1:-1:-1;;;;;6552:15:38;;;;;;:9;:15;;;;;6570:19;;;;6552:37;;6074:540;-1:-1:-1;;;;;6628:16:38;;6624:425;;6791:12;:21;;;;;;;6624:425;;;-1:-1:-1;;;;;7002:13:38;;;;;;:9;:13;;;;;:22;;;;;;6624:425;7079:2;-1:-1:-1;;;;;7064:25:38;7073:4;-1:-1:-1;;;;;7064:25:38;;7083:5;7064:25;;;;6155::46;;6143:2;6128:18;;6009:177;7064:25:38;;;;;;;;5989:1107;;;:::o;17612:266:27:-;17677:15;;17724:33;17736:21;17724:9;:33;:::i;:::-;17704:53;-1:-1:-1;;;;;;17771:28:27;;17767:70;;;17808:29;;-1:-1:-1;;;17808:29:27;;;;;6155:25:46;;;6128:18;;17808:29:27;6009:177:46;598:506:32;791:18;;732:17;;791:22;;;934:163;;1074:7;1083:13;1057:40;;;;;;;;34366:19:46;;;34441:3;34419:16;-1:-1:-1;;;;;;34415:51:46;34410:2;34401:12;;34394:73;34492:2;34483:12;;34211:290;1057:40:32;;;;;;;;;;;;;934:163;;;976:7;985:13;1017:10;1030:11;959:83;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;934:163;927:170;;598:506;;;;;;:::o;1528:478:44:-;1689:20;1711:24;1782:44;1793:9;1804:12;1818:7;1782:10;:44::i;:::-;1747:79;;-1:-1:-1;1747:79:44;-1:-1:-1;1836:11:44;1850:31;1747:79;;1850:31;:::i;:::-;1836:45;-1:-1:-1;1895:7:44;;1891:69;;1935:8;;1918:31;;1928:5;;-1:-1:-1;;;;;1935:8:44;1945:3;1918:9;:31::i;:::-;1969:30;1975:5;1982:16;1969:5;:30::i;:::-;1737:269;1528:478;;;;;;;:::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:38:-;-1:-1:-1;;;;;7509:21:38;;7505:91;;7553:32;;-1:-1:-1;;;7553:32:38;;7582:1;7553:32;;;3587:51:46;3560:18;;7553:32:38;3441:203:46;7505:91:38;7605:35;7621:1;7625:7;7634:5;7605:7;:35::i;7965:206::-;-1:-1:-1;;;;;8035:21:38;;8031:89;;8079:30;;-1:-1:-1;;;8079:30:38;;8106:1;8079:30;;;3587:51:46;3560:18;;8079:30:38;3441:203:46;8031:89:38;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;;;6155:25:46;6128:18;;4781:26:13;6009:177:46;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:41;;;5578:10:13;1745:53:41;;;35811:34:46;;;5598:8:13;-1:-1:-1;;;;;35881:15:46;;;35861:18;;;35854:43;35913:18;;;;35906:34;;;1745:53:41;;;;;;;;;;35746:18:46;;;;1745:53:41;;;;;;;;;-1:-1:-1;;;;;1745:53:41;-1:-1:-1;;;1745:53:41;;;8600:11;;5545:76:13;;:32;;;5609:11;;1718:81:41;;5545:32:13;;-1:-1:-1;;;;1745:53:41;;-1:-1:-1;;;5545:32:13;8566:5:41;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:41;8910:8;8866:16;;-1:-1:-1;8942:15:41;;:68;;8994:11;9009:1;8994:16;;8942:68;;;-1:-1:-1;;;;;8960:26:41;;;:31;8942:68;8938:146;;;9033:40;;-1:-1:-1;;;9033:40:41;;-1:-1:-1;;;;;3605:32:46;;9033:40:41;;;3587:51:46;3560:18;;9033:40:41;3441:203:46;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:250:46:-;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:46;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:46;488:39;;;;529:4;484:50;;269:271;-1:-1:-1;;269:271:46: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:46;;835:42;;825:70;;891:1;888;881:12;906:315;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;1211:2;1196:18;;;;1183:32;;-1:-1:-1;;;906:315:46:o;1418:158::-;1480:5;1525:3;1516:6;1511:3;1507:16;1503:26;1500:46;;;1542:1;1539;1532:12;1500:46;-1:-1:-1;1564:6:46;1418:158;-1:-1:-1;1418:158:46:o;1581:360::-;1669:6;1722:2;1710:9;1701:7;1697:23;1693:32;1690:52;;;1738:1;1735;1728:12;1690:52;1778:9;1765:23;-1:-1:-1;;;;;1803:6:46;1800:30;1797:50;;;1843:1;1840;1833:12;1797:50;1866:69;1927:7;1918:6;1907:9;1903:22;1866:69;:::i;2100:1336::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;2466:4;2514:3;2499:19;;2591:2;2629:3;2624:2;2613:9;2609:18;2602:31;2653:6;2688;2682:13;2719:6;2711;2704:22;2757:3;2746:9;2742:19;2735:26;;2820:3;2810:6;2807:1;2803:14;2792:9;2788:30;2784:40;2770:54;;2843:4;2882;2874:6;2870:17;2905:1;2915:429;2929:6;2926:1;2923:13;2915:429;;;2994:22;;;-1:-1:-1;;2990:37:46;2978:50;;3051:13;;3092:9;;3077:25;;3141:11;;3135:18;3173:15;;;3166:27;;;3216:48;3248:15;;;3135:18;3216:48;:::i;:::-;3206:58;-1:-1:-1;;3322:12:46;;;;3287:15;;;;2951:1;2944:9;2915:429;;;-1:-1:-1;;2020:12:46;;3426:2;3411:18;;2008:25;-1:-1:-1;;;2082:4:46;2071:16;;2065:23;2049:14;;;2042:47;-1:-1:-1;3361:6:46;-1:-1:-1;3376:54:46;1946:149;3649:154;3708:5;3753:2;3744:6;3739:3;3735:16;3731:25;3728:45;;;3769:1;3766;3759:12;3808:347;3859:8;3869:6;3923:3;3916:4;3908:6;3904:17;3900:27;3890:55;;3941:1;3938;3931:12;3890:55;-1:-1:-1;3964:20:46;;-1:-1:-1;;;;;3996:30:46;;3993:50;;;4039:1;4036;4029:12;3993:50;4076:4;4068:6;4064:17;4052:29;;4128:3;4121:4;4112:6;4104;4100:19;4096:30;4093:39;4090:59;;;4145:1;4142;4135:12;4090:59;3808:347;;;;;:::o;4160:1046::-;4301:6;4309;4317;4325;4333;4341;4349;4402:3;4390:9;4381:7;4377:23;4373:33;4370:53;;;4419:1;4416;4409:12;4370:53;4442;4487:7;4476:9;4442:53;:::i;:::-;4432:63;;4542:2;4531:9;4527:18;4514:32;4504:42;;4597:3;4586:9;4582:19;4569:33;-1:-1:-1;;;;;4662:2:46;4654:6;4651:14;4648:34;;;4678:1;4675;4668:12;4648:34;4717:58;4767:7;4758:6;4747:9;4743:22;4717:58;:::i;:::-;4794:8;;-1:-1:-1;4691:84:46;-1:-1:-1;4879:3:46;4864:19;;4851:33;;-1:-1:-1;4893:31:46;4851:33;4893:31;:::i;:::-;4943:5;;-1:-1:-1;5001:3:46;4986:19;;4973:33;;5018:16;;;5015:36;;;5047:1;5044;5037:12;5015:36;;5086:60;5138:7;5127:8;5116:9;5112:24;5086:60;:::i;:::-;4160:1046;;;;-1:-1:-1;4160:1046:46;;-1:-1:-1;4160:1046:46;;;;5060:86;;-1:-1:-1;;;4160:1046:46:o;6191:456::-;6268:6;6276;6284;6337:2;6325:9;6316:7;6312:23;6308:32;6305:52;;;6353:1;6350;6343:12;6305:52;6392:9;6379:23;6411:31;6436:5;6411:31;:::i;:::-;6461:5;-1:-1:-1;6518:2:46;6503:18;;6490:32;6531:33;6490:32;6531:33;:::i;:::-;6191:456;;6583:7;;-1:-1:-1;;;6637:2:46;6622:18;;;;6609:32;;6191:456::o;6841:163::-;6908:20;;6968:10;6957:22;;6947:33;;6937:61;;6994:1;6991;6984:12;6937:61;6841:163;;;:::o;7009:184::-;7067:6;7120:2;7108:9;7099:7;7095:23;7091:32;7088:52;;;7136:1;7133;7126:12;7088:52;7159:28;7177:9;7159:28;:::i;7472:252::-;7539:6;7547;7600:2;7588:9;7579:7;7575:23;7571:32;7568:52;;;7616:1;7613;7606:12;7568:52;7639:28;7657:9;7639:28;:::i;7729:118::-;7815:5;7808:13;7801:21;7794:5;7791:32;7781:60;;7837:1;7834;7827:12;7852:489;7946:6;7954;8007:2;7995:9;7986:7;7982:23;7978:32;7975:52;;;8023:1;8020;8013:12;7975:52;8063:9;8050:23;-1:-1:-1;;;;;8088:6:46;8085:30;8082:50;;;8128:1;8125;8118:12;8082:50;8151:69;8212:7;8203:6;8192:9;8188:22;8151:69;:::i;:::-;8141:79;;;8270:2;8259:9;8255:18;8242:32;8283:28;8305:5;8283:28;:::i;:::-;8330:5;8320:15;;;7852:489;;;;;:::o;8346:253::-;2020:12;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;;2042:47;8536:2;8521:18;;8548:45;1946:149;8604:159;8671:20;;8731:6;8720:18;;8710:29;;8700:57;;8753:1;8750;8743:12;8768:184;8826:6;8879:2;8867:9;8858:7;8854:23;8850:32;8847:52;;;8895:1;8892;8885:12;8847:52;8918:28;8936:9;8918:28;:::i;8957:247::-;9016:6;9069:2;9057:9;9048:7;9044:23;9040:32;9037:52;;;9085:1;9082;9075:12;9037:52;9124:9;9111:23;9143:31;9168:5;9143:31;:::i;9209:256::-;9275:6;9283;9336:2;9324:9;9315:7;9311:23;9307:32;9304:52;;;9352:1;9349;9342:12;9304:52;9375:28;9393:9;9375:28;:::i;:::-;9365:38;;9422:37;9455:2;9444:9;9440:18;9422:37;:::i;:::-;9412:47;;9209:256;;;;;:::o;10186:385::-;10258:6;10266;10274;10327:2;10315:9;10306:7;10302:23;10298:32;10295:52;;;10343:1;10340;10333:12;10295:52;10366:28;10384:9;10366:28;:::i;:::-;10356:38;;10413:37;10446:2;10435:9;10431:18;10413:37;:::i;:::-;10403:47;;10500:2;10489:9;10485:18;10472:32;10513:28;10535:5;10513:28;:::i;:::-;10560:5;10550:15;;;10186:385;;;;;:::o;10781:668::-;10893:6;10901;10909;10917;10970:3;10958:9;10949:7;10945:23;10941:33;10938:53;;;10987:1;10984;10977:12;10938:53;11010;11055:7;11044:9;11010:53;:::i;:::-;11000:63;;11114:2;11103:9;11099:18;11086:32;-1:-1:-1;;;;;11133:6:46;11130:30;11127:50;;;11173:1;11170;11163:12;11127:50;11212:58;11262:7;11253:6;11242:9;11238:22;11212:58;:::i;:::-;11289:8;;-1:-1:-1;11186:84:46;-1:-1:-1;;11374:3:46;11359:19;;11346:33;11388:31;11346:33;11388:31;:::i;:::-;10781:668;;;;-1:-1:-1;10781:668:46;;-1:-1:-1;;10781:668:46:o;11454:395::-;11545:8;11555:6;11609:3;11602:4;11594:6;11590:17;11586:27;11576:55;;11627:1;11624;11617:12;11576:55;-1:-1:-1;11650:20:46;;-1:-1:-1;;;;;11682:30:46;;11679:50;;;11725:1;11722;11715:12;11679:50;11762:4;11754:6;11750:17;11738:29;;11822:3;11815:4;11805:6;11802:1;11798:14;11790:6;11786:27;11782:38;11779:47;11776:67;;;11839:1;11836;11829:12;11854:504;11979:6;11987;12040:2;12028:9;12019:7;12015:23;12011:32;12008:52;;;12056:1;12053;12046:12;12008:52;12096:9;12083:23;-1:-1:-1;;;;;12121:6:46;12118:30;12115:50;;;12161:1;12158;12151:12;12115:50;12200:98;12290:7;12281:6;12270:9;12266:22;12200:98;:::i;:::-;12317:8;;12174:124;;-1:-1:-1;11854:504:46;-1:-1:-1;;;;11854:504:46:o;12545:553::-;12631:6;12639;12647;12655;12708:2;12696:9;12687:7;12683:23;12679:32;12676:52;;;12724:1;12721;12714:12;12676:52;12747:28;12765:9;12747:28;:::i;:::-;12737:38;;12794:37;12827:2;12816:9;12812:18;12794:37;:::i;:::-;12784:47;;12882:2;12871:9;12867:18;12854:32;-1:-1:-1;;;;;12901:6:46;12898:30;12895:50;;;12941:1;12938;12931:12;12895:50;12980:58;13030:7;13021:6;13010:9;13006:22;12980:58;:::i;:::-;12545:553;;;;-1:-1:-1;13057:8:46;-1:-1:-1;;;;12545:553:46:o;13606:655::-;13742:6;13750;13758;13802:9;13793:7;13789:23;13832:3;13828:2;13824:12;13821:32;;;13849:1;13846;13839:12;13821:32;13889:9;13876:23;-1:-1:-1;;;;;13914:6:46;13911:30;13908:50;;;13954:1;13951;13944:12;13908:50;13977:69;14038:7;14029:6;14018:9;14014:22;13977:69;:::i;:::-;13967:79;-1:-1:-1;;14080:2:46;-1:-1:-1;;14062:16:46;;14058:25;14055:45;;;14096:1;14093;14086:12;14055:45;;14134:2;14123:9;14119:18;14109:28;;14187:2;14176:9;14172:18;14159:32;14200:31;14225:5;14200:31;:::i;14266:609::-;14506:4;14548:3;14537:9;14533:19;14525:27;;14585:6;14579:13;14568:9;14561:32;-1:-1:-1;;;;;14653:4:46;14645:6;14641:17;14635:24;14631:49;14624:4;14613:9;14609:20;14602:79;14728:4;14720:6;14716:17;14710:24;14743:62;14799:4;14788:9;14784:20;14770:12;2020;;2008:25;;2082:4;2071:16;;;2065:23;2049:14;;2042:47;1946:149;14743:62;-1:-1:-1;2020:12:46;;14864:3;14849:19;;2008:25;2082:4;2071:16;;2065:23;2049:14;;;2042:47;14814:55;1946:149;14880:388;14948:6;14956;15009:2;14997:9;14988:7;14984:23;14980:32;14977:52;;;15025:1;15022;15015:12;14977:52;15064:9;15051:23;15083:31;15108:5;15083:31;:::i;:::-;15133:5;-1:-1:-1;15190:2:46;15175:18;;15162:32;15203:33;15162:32;15203:33;:::i;15273:234::-;15356:6;15409:2;15397:9;15388:7;15384:23;15380:32;15377:52;;;15425:1;15422;15415:12;15377:52;15448:53;15493:7;15482:9;15448:53;:::i;15512:380::-;15591:1;15587:12;;;;15634;;;15655:61;;15709:4;15701:6;15697:17;15687:27;;15655:61;15762:2;15754:6;15751:14;15731:18;15728:38;15725:161;;15808:10;15803:3;15799:20;15796:1;15789:31;15843:4;15840:1;15833:15;15871:4;15868:1;15861:15;15897:251;15967:6;16020:2;16008:9;15999:7;15995:23;15991:32;15988:52;;;16036:1;16033;16026:12;15988:52;16068:9;16062:16;16087:31;16112:5;16087:31;:::i;16153:184::-;16223:6;16276:2;16264:9;16255:7;16251:23;16247:32;16244:52;;;16292:1;16289;16282:12;16244:52;-1:-1:-1;16315:16:46;;16153:184;-1:-1:-1;16153:184:46:o;16342:127::-;16403:10;16398:3;16394:20;16391:1;16384:31;16434:4;16431:1;16424:15;16458:4;16455:1;16448:15;16742:127;16803:10;16798:3;16794:20;16791:1;16784:31;16834:4;16831:1;16824:15;16858:4;16855:1;16848:15;16874:168;16947:9;;;16978;;16995:15;;;16989:22;;16975:37;16965:71;;17016:18;;:::i;17047:217::-;17087:1;17113;17103:132;;17157:10;17152:3;17148:20;17145:1;17138:31;17192:4;17189:1;17182:15;17220:4;17217:1;17210:15;17103:132;-1:-1:-1;17249:9:46;;17047:217::o;17629:253::-;17701:2;17695:9;17743:4;17731:17;;-1:-1:-1;;;;;17763:34:46;;17799:22;;;17760:62;17757:88;;;17825:18;;:::i;:::-;17861:2;17854:22;17629:253;:::o;17887:257::-;17959:4;17953:11;;;17991:17;;-1:-1:-1;;;;;18023:34:46;;18059:22;;;18020:62;18017:88;;;18085:18;;:::i;18149:275::-;18220:2;18214:9;18285:2;18266:13;;-1:-1:-1;;18262:27:46;18250:40;;-1:-1:-1;;;;;18305:34:46;;18341:22;;;18302:62;18299:88;;;18367:18;;:::i;:::-;18403:2;18396:22;18149:275;;-1:-1:-1;18149:275:46:o;18429:186::-;18477:4;-1:-1:-1;;;;;18502:6:46;18499:30;18496:56;;;18532:18;;:::i;:::-;-1:-1:-1;18598:2:46;18577:15;-1:-1:-1;;18573:29:46;18604:4;18569:40;;18429:186::o;18620:2117::-;18812:9;-1:-1:-1;;;;;18887:2:46;18879:6;18876:14;18873:40;;;18893:18;;:::i;:::-;18939:6;18936:1;18932:14;18965:4;18989:28;19013:2;19009;19005:11;18989:28;:::i;:::-;19051:19;;;19121:14;;;;19086:12;;;;19158:14;19147:26;;19144:46;;;19186:1;19183;19176:12;19144:46;19210:5;19224:1480;19240:6;19235:3;19232:15;19224:1480;;;19326:3;19313:17;19362:2;19349:11;19346:19;19343:109;;;19406:1;19435:2;19431;19424:14;19343:109;19475:23;;19543:4;19522:14;19518:23;;;19514:34;19511:124;;;19589:1;19618:2;19614;19607:14;19511:124;19663:22;;:::i;:::-;19714:21;19732:2;19714:21;:::i;:::-;19705:7;19698:38;19774:30;19800:2;19796;19792:11;19774:30;:::i;:::-;19769:2;19760:7;19756:16;19749:56;19828:2;19878;19874;19870:11;19857:25;19909:2;19901:6;19898:14;19895:104;;;19953:1;19982:2;19978;19971:14;19895:104;20022:15;;;;;20079:14;20072:4;20064:13;;20060:34;20050:135;;20137:1;20167:3;20162;20155:16;20050:135;20222:2;20209:16;20251:49;20267:32;20295:3;20267:32;:::i;:::-;20251:49;:::i;:::-;20327:3;20320:5;20313:18;20373:14;20368:2;20362:3;20358:2;20354:12;20350:21;20347:41;20344:134;;;20430:1;20460:3;20455;20448:16;20344:134;20533:3;20528:2;20524;20520:11;20515:2;20508:5;20504:14;20491:46;20583:1;20561:15;;;20557:24;;20550:35;;;;20605:16;;;20598:31;20642:20;;-1:-1:-1;20682:12:46;;;;19257;;19224:1480;;;-1:-1:-1;20726:5:46;18620:2117;-1:-1:-1;;;;;;;18620:2117:46:o;20742:331::-;20847:9;20858;20900:8;20888:10;20885:24;20882:44;;;20922:1;20919;20912:12;20882:44;20951:6;20941:8;20938:20;20935:40;;;20971:1;20968;20961:12;20935:40;-1:-1:-1;;20997:23:46;;;21042:25;;;;;-1:-1:-1;20742:331:46:o;21078:476::-;21269:3;21307:6;21301:13;21323:66;21382:6;21377:3;21370:4;21362:6;21358:17;21323:66;:::i;:::-;21411:16;;21464:6;21456;21411:16;21436:35;21528:1;21490:18;;21517:13;;;-1:-1:-1;21490:18:46;;21078:476;-1:-1:-1;;;21078:476:46:o;21559:266::-;21647:6;21642:3;21635:19;21699:6;21692:5;21685:4;21680:3;21676:14;21663:43;-1:-1:-1;21751:1:46;21726:16;;;21744:4;21722:27;;;21715:38;;;;21807:2;21786:15;;;-1:-1:-1;;21782:29:46;21773:39;;;21769:50;;21559:266::o;21830:244::-;21987:2;21976:9;21969:21;21950:4;22007:61;22064:2;22053:9;22049:18;22041:6;22033;22007:61;:::i;22079:127::-;22140:10;22135:3;22131:20;22128:1;22121:31;22171:4;22168:1;22161:15;22195:4;22192:1;22185:15;22211:331;22310:4;22368:11;22355:25;22462:3;22458:8;22447;22431:14;22427:29;22423:44;22403:18;22399:69;22389:97;;22482:1;22479;22472:12;22389:97;22503:33;;;;;22211:331;-1:-1:-1;;22211:331:46:o;22547:521::-;22624:4;22630:6;22690:11;22677:25;22784:2;22780:7;22769:8;22753:14;22749:29;22745:43;22725:18;22721:68;22711:96;;22803:1;22800;22793:12;22711:96;22830:33;;22882:20;;;-1:-1:-1;;;;;;22914:30:46;;22911:50;;;22957:1;22954;22947:12;22911:50;22990:4;22978:17;;-1:-1:-1;23021:14:46;23017:27;;;23007:38;;23004:58;;;23058:1;23055;23048:12;23073:129;-1:-1:-1;;;;;23151:5:46;23147:30;23140:5;23137:41;23127:69;;23192:1;23189;23182:12;23207:988;23581:10;23554:25;23572:6;23554:25;:::i;:::-;23550:42;23539:9;23532:61;23656:4;23648:6;23644:17;23631:31;23624:4;23613:9;23609:20;23602:61;23513:4;23710;23702:6;23698:17;23685:31;23725:30;23749:5;23725:30;:::i;:::-;-1:-1:-1;;;;;23797:5:46;23793:30;23786:4;23775:9;23771:20;23764:60;;23860:6;23855:2;23844:9;23840:18;23833:34;23904:3;23898;23887:9;23883:19;23876:32;23931:62;23988:3;23977:9;23973:19;23965:6;23957;23931:62;:::i;:::-;-1:-1:-1;;;;;24030:32:46;;24050:3;24009:19;;24002:61;24100:22;;;24094:3;24079:19;;24072:51;24140:49;24104:6;24174;24166;24140:49;:::i;:::-;24132:57;23207:988;-1:-1:-1;;;;;;;;;;23207:988:46:o;24200:647::-;24279:6;24332:2;24320:9;24311:7;24307:23;24303:32;24300:52;;;24348:1;24345;24338:12;24300:52;24381:9;24375:16;-1:-1:-1;;;;;24406:6:46;24403:30;24400:50;;;24446:1;24443;24436:12;24400:50;24469:22;;24522:4;24514:13;;24510:27;-1:-1:-1;24500:55:46;;24551:1;24548;24541:12;24500:55;24580:2;24574:9;24605:48;24621:31;24649:2;24621:31;:::i;24605:48::-;24676:2;24669:5;24662:17;24716:7;24711:2;24706;24702;24698:11;24694:20;24691:33;24688:53;;;24737:1;24734;24727:12;24688:53;24750:67;24814:2;24809;24802:5;24798:14;24793:2;24789;24785:11;24750:67;:::i;24852:128::-;24919:9;;;24940:11;;;24937:37;;;24954:18;;:::i;25435:245::-;25493:6;25546:2;25534:9;25525:7;25521:23;25517:32;25514:52;;;25562:1;25559;25552:12;25514:52;25601:9;25588:23;25620:30;25644:5;25620:30;:::i;25685:479::-;25952:1;25948;25943:3;25939:11;25935:19;25927:6;25923:32;25912:9;25905:51;25992:6;25987:2;25976:9;25972:18;25965:34;26047:6;26039;26035:19;26030:2;26019:9;26015:18;26008:47;26091:3;26086:2;26075:9;26071:18;26064:31;25886:4;26112:46;26153:3;26142:9;26138:19;26130:6;26112:46;:::i;26787:379::-;26980:2;26969:9;26962:21;26943:4;27006:45;27047:2;27036:9;27032:18;27024:6;27006:45;:::i;:::-;27099:9;27091:6;27087:22;27082:2;27071:9;27067:18;27060:50;27127:33;27153:6;27145;27127:33;:::i;27171:245::-;27238:6;27291:2;27279:9;27270:7;27266:23;27262:32;27259:52;;;27307:1;27304;27297:12;27259:52;27339:9;27333:16;27358:28;27380:5;27358:28;:::i;27421:887::-;27640:2;27629:9;27622:21;27698:10;27689:6;27683:13;27679:30;27674:2;27663:9;27659:18;27652:58;27764:4;27756:6;27752:17;27746:24;27741:2;27730:9;27726:18;27719:52;27603:4;27818:2;27810:6;27806:15;27800:22;27859:4;27853:3;27842:9;27838:19;27831:33;27887:52;27934:3;27923:9;27919:19;27905:12;27887:52;:::i;:::-;27873:66;;27988:2;27980:6;27976:15;27970:22;28062:2;28058:7;28046:9;28038:6;28034:22;28030:36;28023:4;28012:9;28008:20;28001:66;28090:41;28124:6;28108:14;28090:41;:::i;:::-;28200:3;28188:16;;;;28182:23;28175:31;28168:39;28162:3;28147:19;;28140:68;-1:-1:-1;;;;;;;;28269:32:46;;;;28262:4;28247:20;;;28240:62;28076:55;27421:887::o;28313:284::-;28383:5;28431:4;28419:9;28414:3;28410:19;28406:30;28403:50;;;28449:1;28446;28439:12;28403:50;28471:22;;:::i;:::-;28462:31;;28522:9;28516:16;28509:5;28502:31;28586:2;28575:9;28571:18;28565:25;28560:2;28553:5;28549:14;28542:49;28313:284;;;;:::o;28602:257::-;28700:6;28753:2;28741:9;28732:7;28728:23;28724:32;28721:52;;;28769:1;28766;28759:12;28721:52;28792:61;28845:7;28834:9;28792:61;:::i;28989:542::-;29090:2;29085:3;29082:11;29079:446;;;29126:1;29150:5;29147:1;29140:16;29194:4;29191:1;29181:18;29264:2;29252:10;29248:19;29245:1;29241:27;29235:4;29231:38;29300:4;29288:10;29285:20;29282:47;;;-1:-1:-1;29323:4:46;29282:47;29378:2;29373:3;29369:12;29366:1;29362:20;29356:4;29352:31;29342:41;;29433:82;29451:2;29444:5;29441:13;29433:82;;;29496:17;;;29477:1;29466:13;29433:82;;;29437:3;;;28989:542;;;:::o;29707:1341::-;29831:3;29825:10;-1:-1:-1;;;;;29850:6:46;29847:30;29844:56;;;29880:18;;:::i;:::-;29909:96;29998:6;29958:38;29990:4;29984:11;29958:38;:::i;:::-;29952:4;29909:96;:::i;:::-;30060:4;;30117:2;30106:14;;30134:1;30129:662;;;;30835:1;30852:6;30849:89;;;-1:-1:-1;30904:19:46;;;30898:26;30849:89;-1:-1:-1;;29664:1:46;29660:11;;;29656:24;29652:29;29642:40;29688:1;29684:11;;;29639:57;30951:81;;30099:943;;30129:662;28936:1;28929:14;;;28973:4;28960:18;;-1:-1:-1;;30165:20:46;;;30282:236;30296:7;30293:1;30290:14;30282:236;;;30385:19;;;30379:26;30364:42;;30477:27;;;;30445:1;30433:14;;;;30312:19;;30282:236;;;30286:3;30546:6;30537:7;30534:19;30531:201;;;30607:19;;;30601:26;-1:-1:-1;;30690:1:46;30686:14;;;30702:3;30682:24;30678:37;30674:42;30659:58;30644:74;;30531:201;-1:-1:-1;;;;;30778:1:46;30762:14;;;30758:22;30745:36;;-1:-1:-1;29707:1341:46:o;31053:1164::-;31269:4;31298:2;31338;31327:9;31323:18;31368:2;31357:9;31350:21;31391:6;31426;31420:13;31457:6;31449;31442:22;31483:2;31473:12;;31516:2;31505:9;31501:18;31494:25;;31578:2;31568:6;31565:1;31561:14;31550:9;31546:30;31542:39;31616:2;31608:6;31604:15;31637:1;31647:541;31661:6;31658:1;31655:13;31647:541;;;31726:22;;;-1:-1:-1;;31722:36:46;31710:49;;31782:13;;31854:9;;31865:10;31850:26;31835:42;;31924:11;;;31918:18;31938:6;31914:31;31897:15;;;31890:56;31985:11;;31979:18;31818:4;32017:15;;;32010:27;;;32060:48;32092:15;;;31979:18;32060:48;:::i;:::-;32166:12;;;;32050:58;-1:-1:-1;;;32131:15:46;;;;31683:1;31676:9;31647:541;;;-1:-1:-1;32205:6:46;;31053:1164;-1:-1:-1;;;;;;;;31053:1164:46:o;32222:346::-;32309:6;32362:2;32350:9;32341:7;32337:23;32333:32;32330:52;;;32378:1;32375;32368:12;32330:52;32404:22;;:::i;:::-;32462:9;32449:23;32442:5;32435:38;32533:2;32522:9;32518:18;32505:32;32500:2;32493:5;32489:14;32482:56;32557:5;32547:15;;;32222:346;;;;:::o;32912:255::-;33032:19;;33071:2;33063:11;;33060:101;;;-1:-1:-1;;33132:2:46;33128:12;;;33125:1;33121:20;33117:33;33106:45;32912:255;;;;:::o;33172:331::-;-1:-1:-1;;;;;;33292:19:46;;33376:11;;;;33407:1;33399:10;;33396:101;;;33484:2;33478;33471:3;33468:1;33464:11;33461:1;33457:19;33453:28;33449:2;33445:37;33441:46;33432:55;;33396:101;;;33172:331;;;;:::o;33508:568::-;-1:-1:-1;;;;;33773:3:46;33769:28;33760:6;33755:3;33751:16;33747:51;33742:3;33735:64;33859:10;33854:3;33850:20;33841:6;33836:3;33832:16;33828:43;33824:1;33819:3;33815:11;33808:64;33902:6;33897:2;33892:3;33888:12;33881:28;33717:3;33938:6;33932:13;33954:75;34022:6;34017:2;34012:3;34008:12;34001:4;33993:6;33989:17;33954:75;:::i;:::-;34049:16;;;;34067:2;34045:25;;33508:568;-1:-1:-1;;;;;33508:568:46:o;34081:125::-;34146:9;;;34167:10;;;34164:36;;;34180:18;;:::i;34506:532::-;34747:6;34742:3;34735:19;-1:-1:-1;;;;;34810:3:46;34806:28;34797:6;34792:3;34788:16;34784:51;34779:2;34774:3;34770:12;34763:73;34866:6;34861:2;34856:3;34852:12;34845:28;34717:3;34902:6;34896:13;34918:73;34984:6;34979:2;34974:3;34970:12;34965:2;34957:6;34953:15;34918:73;:::i;:::-;35011:16;;;;35029:2;35007:25;;34506:532;-1:-1:-1;;;;;34506:532:46:o;35043:523::-;35145:6;35198:3;35186:9;35177:7;35173:23;35169:33;35166:53;;;35215:1;35212;35205:12;35166:53;35241:22;;:::i;:::-;35292:9;35286:16;35279:5;35272:31;35348:2;35337:9;35333:18;35327:25;35361:32;35385:7;35361:32;:::i;:::-;35420:2;35409:14;;35402:31;35465:70;35527:7;35522:2;35507:18;;35465:70;:::i;:::-;35460:2;35449:14;;35442:94;35453:5;35043:523;-1:-1:-1;;;35043:523:46:o
Swarm Source
ipfs://da31c6192c431a4475e8627e64ad04324c8ba067ca5e705a81e3b2940bfe4881
Loading...
Loading
Loading...
Loading
OVERVIEW
Wrapped Bitcoin (WBTC) is an ERC20 token backed 1:1 with Bitcoin. Completely transparent. 100% verifiable. Community led.Loading...
Loading
Net Worth in USD
$132,430,166.54
Net Worth in MON
Token Allocations
WBTC
100.00%
BTCB
0.00%
POL
0.00%
Others
0.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $89,172 | 1,485.1027 | $132,429,576.06 | |
| ETH | <0.01% | $0.000147 | 725 | $0.1063 | |
| BSC | <0.01% | $89,419.04 | 0.00462414 | $413.49 | |
| BSC | <0.01% | $89,182 | 0.00011204 | $9.99 | |
| BASE | <0.01% | $89,145 | 0.00157758 | $140.63 | |
| BASE | <0.01% | $0.195083 | 10 | $1.95 | |
| BASE | <0.01% | $0.155996 | 1.5487 | $0.2415 | |
| SONIC | <0.01% | $89,197 | 0.000175 | $15.61 | |
| POL | <0.01% | $0.126977 | 56 | $7.11 | |
| SEI | <0.01% | $89,185 | 0.0000113 | $1.01 | |
| ARB | <0.01% | $2,956.76 | 0.00006302 | $0.186335 | |
| WORLD | <0.01% | $89,182 | 0.00000177 | $0.1578 | |
| MANTLE | <0.01% | $0.894566 | 0.00080894 | $0.000724 |
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.