You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.7 KiB
115 lines
3.7 KiB
9 months ago
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||
|
pragma solidity >=0.8.0;
|
||
|
|
||
|
/*@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@@@@@@@@@@@@@@@@@
|
||
|
@@@@@ HYPERLANE @@@@@@@
|
||
|
@@@@@@@@@@@@@@@@@@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@@
|
||
|
@@@@@@@@@ @@@@@@@@*/
|
||
|
|
||
|
// ============ Internal Imports ============
|
||
|
|
||
|
import {IInterchainSecurityModule} from "../../../interfaces/IInterchainSecurityModule.sol";
|
||
|
import {Message} from "../../../libs/Message.sol";
|
||
|
import {TypeCasts} from "../../../libs/TypeCasts.sol";
|
||
|
import {AbstractMessageIdAuthorizedIsm} from "../AbstractMessageIdAuthorizedIsm.sol";
|
||
|
|
||
|
// ============ External Imports ============
|
||
|
import {Origin} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
|
||
|
|
||
|
/**
|
||
|
* @title LayerZeroV2Ism
|
||
|
* @notice Uses LayerZero V2 deliver and verify a messages Id
|
||
|
*/
|
||
|
contract LayerZeroV2Ism is AbstractMessageIdAuthorizedIsm {
|
||
|
using Message for bytes;
|
||
|
using TypeCasts for bytes32;
|
||
|
|
||
|
// Layerzero endpoint address
|
||
|
address public immutable endpoint;
|
||
|
|
||
|
// ============ Constants ============
|
||
|
|
||
|
uint8 public constant moduleType =
|
||
|
uint8(IInterchainSecurityModule.Types.NULL);
|
||
|
|
||
|
// @dev the offset of msg.data where the function parameters (as bytes) begins. 4 bytes is always used when encoding the function selector
|
||
|
uint8 constant FUNC_SELECTOR_OFFSET = 4;
|
||
|
|
||
|
// @dev the offset of msg.data where Origin.sender begins. 32 is always used since calldata comes in 32 bytes.
|
||
|
uint8 constant ORIGIN_SENDER_OFFSET = FUNC_SELECTOR_OFFSET + 32;
|
||
|
|
||
|
// ============ Constructor ============
|
||
|
constructor(address _endpoint) {
|
||
|
require(
|
||
|
_endpoint != address(0),
|
||
|
"LayerZeroV2Ism: invalid authorized endpoint"
|
||
|
);
|
||
|
endpoint = _endpoint;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @notice Entry point for receiving msg/packet from the LayerZero endpoint.
|
||
|
* @param _lzMessage The payload of the received message.
|
||
|
* @dev Authorization verifcation is done within verifyMessageId() -> _isAuthorized()
|
||
|
*/
|
||
|
function lzReceive(
|
||
|
Origin calldata,
|
||
|
bytes32,
|
||
|
bytes calldata _lzMessage,
|
||
|
address,
|
||
|
bytes calldata
|
||
|
) external payable {
|
||
|
verifyMessageId(_messageId(_lzMessage));
|
||
|
}
|
||
|
|
||
|
// ============ Internal function ============
|
||
|
|
||
|
/**
|
||
|
* @notice Slices the messageId from the message delivered from LayerZeroV2Hook
|
||
|
* @dev message is created as abi.encodeCall(AbstractMessageIdAuthorizedIsm.verifyMessageId, id)
|
||
|
* @dev _message will be 36 bytes (4 bytes for function selector, and 32 bytes for messageId)
|
||
|
*/
|
||
|
function _messageId(
|
||
|
bytes calldata _message
|
||
|
) internal pure returns (bytes32) {
|
||
|
return bytes32(_message[FUNC_SELECTOR_OFFSET:]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @notice Validates criterias to verify a message
|
||
|
* @dev this is called by AbstractMessageIdAuthorizedIsm.verifyMessageId
|
||
|
* @dev parses msg.value to get parameters from lzReceive()
|
||
|
*/
|
||
|
function _isAuthorized() internal view override returns (bool) {
|
||
|
require(_isAuthorizedHook(), "LayerZeroV2Ism: hook is not authorized");
|
||
|
|
||
|
require(
|
||
|
_isAuthorizedEndPoint(),
|
||
|
"LayerZeroV2Ism: endpoint is not authorized"
|
||
|
);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @notice check if origin.sender is the authorized hook
|
||
|
*/
|
||
|
function _isAuthorizedHook() internal view returns (bool) {
|
||
|
return bytes32(msg.data[ORIGIN_SENDER_OFFSET:]) == authorizedHook;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @notice check if LayerZero endpoint is authorized
|
||
|
*/
|
||
|
function _isAuthorizedEndPoint() internal view returns (bool) {
|
||
|
return msg.sender == endpoint;
|
||
|
}
|
||
|
}
|