Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 52 additions & 15 deletions examples/omni-call/contracts/OmniCall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ pragma solidity 0.8.22;

// ========== External imports ==========

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

// ========== LayerZero imports ==========

import { OApp, MessagingFee, Origin, OAppReceiver } from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import { MessagingReceipt } from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol";
import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
import {OApp, MessagingFee, Origin, OAppReceiver} from "@layerzerolabs/oapp-evm/contracts/oapp/OApp.sol";
import {MessagingReceipt} from "@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol";
import {OptionsBuilder} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";

// ========== Internal imports ==========

import { OmniCallMsgCodecLib, Call, Transfer } from "./OmniCallMsgCodecLib.sol";
import { IOmniCall } from "./interfaces/IOmniCall.sol";
import {OmniCallMsgCodecLib, Call, Transfer} from "./OmniCallMsgCodecLib.sol";
import {IOmniCall} from "./interfaces/IOmniCall.sol";

/// -----------------------------------------------------------------------
/// Contract
Expand Down Expand Up @@ -53,7 +53,10 @@ contract OmniCall is IOmniCall, OApp {
* @param endpoint_: LZ endpoint address;
* @param delegate: address to which permissions are delegated.
*/
constructor(address endpoint_, address delegate) OApp(endpoint_, delegate) Ownable(delegate) {}
constructor(
address endpoint_,
address delegate
) OApp(endpoint_, delegate) Ownable(delegate) {}

/// -----------------------------------------------------------------------
/// State-change public/external functions
Expand All @@ -66,7 +69,12 @@ contract OmniCall is IOmniCall, OApp {
Call calldata dstCall,
Transfer calldata dstTransfer,
uint128 dstGasLimit
) external payable override(IOmniCall) returns (MessagingReceipt memory receipt) {
)
external
payable
override(IOmniCall)
returns (MessagingReceipt memory receipt)
{
(MessagingFee memory fee, bytes memory options) = _quoteWithOptions(
messageType,
dstEid,
Expand All @@ -75,8 +83,18 @@ contract OmniCall is IOmniCall, OApp {
dstGasLimit
);

bytes memory encodedPayload = OmniCallMsgCodecLib.encode(messageType, dstCall, dstTransfer);
receipt = _lzSend(dstEid, encodedPayload, options, fee, payable(msg.sender));
bytes memory encodedPayload = OmniCallMsgCodecLib.encode(
messageType,
dstCall,
dstTransfer
);
receipt = _lzSend(
dstEid,
encodedPayload,
options,
fee,
payable(msg.sender)
);
}

/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -129,8 +147,14 @@ contract OmniCall is IOmniCall, OApp {
* @param value: value to be sent with the call;
* @param callData: call calldata.
*/
function _call(address target, uint256 value, bytes memory callData) internal {
(bool success, bytes memory result) = target.call{ value: value }(callData);
function _call(
address target,
uint256 value,
bytes memory callData
) internal {
(bool success, bytes memory result) = target.call{value: value}(
callData
);
if (!success) {
assembly {
revert(add(result, 32), mload(result))
Expand All @@ -150,7 +174,13 @@ contract OmniCall is IOmniCall, OApp {
Transfer calldata dstTransfer,
uint128 dstGasLimit
) external view override(IOmniCall) returns (MessagingFee memory fee) {
(fee, ) = _quoteWithOptions(messageType, dstEid, dstCall, dstTransfer, dstGasLimit);
(fee, ) = _quoteWithOptions(
messageType,
dstEid,
dstCall,
dstTransfer,
dstGasLimit
);
}

/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -187,7 +217,10 @@ contract OmniCall is IOmniCall, OApp {
dstTransfer.value + dstCall.value
);
} else {
options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(dstGasLimit, dstCall.value);
options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(
dstGasLimit,
dstCall.value
);
if (dstTransfer.value > 0) {
options = options.addExecutorNativeDropOption(
dstTransfer.value,
Expand All @@ -196,7 +229,11 @@ contract OmniCall is IOmniCall, OApp {
}
}

bytes memory encodedPayload = OmniCallMsgCodecLib.encode(messageType, dstCall, dstTransfer);
bytes memory encodedPayload = OmniCallMsgCodecLib.encode(
messageType,
dstCall,
dstTransfer
);
fee = _quote(dstEid, encodedPayload, options, false);
}
}
85 changes: 70 additions & 15 deletions examples/omni-call/contracts/OmniCallMsgCodecLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ library OmniCallMsgCodecLib {
* @param messageType: The type of message.
* @param length: The length of the data.
*/
error LZ_OmniCallMsgCodecLib__InvalidDataLength(uint8 messageType, uint256 length);
error LZ_OmniCallMsgCodecLib__InvalidDataLength(
uint8 messageType,
uint256 length
);

/// -----------------------------------------------------------------------
/// Constants
Expand Down Expand Up @@ -88,12 +91,19 @@ library OmniCallMsgCodecLib {
revert LZ_OmniCallMsgCodecLib__InvalidMessageType();
}

uint8 messageTypeUint = (messageType == TRANSFER_TYPE && dstCall.callData.length > 0) ||
uint8 messageTypeUint = (messageType == TRANSFER_TYPE &&
dstCall.callData.length > 0) ||
(messageType == CALL_TYPE && dstTransfer.value > 0)
? messageType + 1
: messageType;
if (messageTypeUint == CALL_TYPE) {
return abi.encodePacked(messageTypeUint, dstCall.target, dstCall.value, dstCall.callData);
return
abi.encodePacked(
messageTypeUint,
dstCall.target,
dstCall.value,
dstCall.callData
);
} else if (messageTypeUint == CALL_AND_TRANSFER_TYPE) {
return
abi.encodePacked(
Expand Down Expand Up @@ -123,25 +133,65 @@ library OmniCallMsgCodecLib {
*/
function decode(
bytes calldata data
) internal pure returns (address to, uint128 transferValue, address target, uint128 value, bytes memory callData) {
)
internal
pure
returns (
address to,
uint128 transferValue,
address target,
uint128 value,
bytes memory callData
)
{
uint8 messageType = uint8(data[0]);
if (messageType == CALL_TYPE) {
if (data.length < MINIMAL_LENGTH_CALL) {
revert LZ_OmniCallMsgCodecLib__InvalidDataLength(messageType, data.length);
revert LZ_OmniCallMsgCodecLib__InvalidDataLength(
messageType,
data.length
);
}

target = address(uint160(bytes20(data[FIRST_ADDRESS_START_INDEX:FIRST_ADDRESS_END_INDEX])));
value = uint128(bytes16(data[FIRST_ADDRESS_END_INDEX:FIRST_VALUE_END_INDEX]));
target = address(
uint160(
bytes20(
data[FIRST_ADDRESS_START_INDEX:FIRST_ADDRESS_END_INDEX]
)
)
);
value = uint128(
bytes16(data[FIRST_ADDRESS_END_INDEX:FIRST_VALUE_END_INDEX])
);
callData = data[FIRST_VALUE_END_INDEX:];
} else if (messageType == CALL_AND_TRANSFER_TYPE) {
if (data.length < MINIMAL_LENGTH_CALL_AND_TRANSFER) {
revert LZ_OmniCallMsgCodecLib__InvalidDataLength(messageType, data.length);
revert LZ_OmniCallMsgCodecLib__InvalidDataLength(
messageType,
data.length
);
}

to = address(uint160(bytes20(data[FIRST_ADDRESS_START_INDEX:FIRST_ADDRESS_END_INDEX])));
transferValue = uint128(bytes16(data[FIRST_ADDRESS_END_INDEX:FIRST_VALUE_END_INDEX]));
target = address(uint160(bytes20(data[FIRST_VALUE_END_INDEX:SECOND_ADDRESS_END_INDEX])));
value = uint128(bytes16(data[SECOND_ADDRESS_END_INDEX:SECOND_VALUE_END_INDEX]));
to = address(
uint160(
bytes20(
data[FIRST_ADDRESS_START_INDEX:FIRST_ADDRESS_END_INDEX]
)
)
);
transferValue = uint128(
bytes16(data[FIRST_ADDRESS_END_INDEX:FIRST_VALUE_END_INDEX])
);
target = address(
uint160(
bytes20(
data[FIRST_VALUE_END_INDEX:SECOND_ADDRESS_END_INDEX]
)
)
);
value = uint128(
bytes16(data[SECOND_ADDRESS_END_INDEX:SECOND_VALUE_END_INDEX])
);
callData = data[SECOND_VALUE_END_INDEX:];
} else {
revert LZ_OmniCallMsgCodecLib__InvalidMessageType();
Expand All @@ -154,15 +204,20 @@ library OmniCallMsgCodecLib {
* @return - bool - True if the message type is a call type, false otherwise.
*/
function isCallType(bytes calldata data) internal pure returns (bool) {
return uint8(data[0]) == CALL_TYPE && data.length >= MINIMAL_LENGTH_CALL;
return
uint8(data[0]) == CALL_TYPE && data.length >= MINIMAL_LENGTH_CALL;
}

/**
* @notice Checks if the message type is a call and transfer type.
* @param data The encoded message.
* @return - bool - True if the message type is a call and transfer type, false otherwise.
*/
function isCallAndTransferType(bytes calldata data) internal pure returns (bool) {
return uint8(data[0]) == CALL_AND_TRANSFER_TYPE && data.length >= MINIMAL_LENGTH_CALL_AND_TRANSFER;
function isCallAndTransferType(
bytes calldata data
) internal pure returns (bool) {
return
uint8(data[0]) == CALL_AND_TRANSFER_TYPE &&
data.length >= MINIMAL_LENGTH_CALL_AND_TRANSFER;
}
}
28 changes: 28 additions & 0 deletions examples/omni-call/script/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.27;

import { Script } from "forge-std/Script.sol";
import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";

import { OmniCall } from "../contracts/OmniCall.sol";
import { HelperConfig } from "./HelperConfig.s.sol";

contract Deploy is Script {
OmniCall public proxy;

HelperConfig public config;

function run() public {
config = new HelperConfig();

(address endpoint, , , , , uint256 key) = config.activeNetworkConfig();
address sender = vm.addr(key);
ILayerZeroEndpointV2 lzEnpoint = ILayerZeroEndpointV2(endpoint);

vm.startBroadcast(key);

proxy = new OmniCall(address(lzEnpoint), sender);

vm.stopBroadcast();
}
}
Loading
Loading