Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added hyperlane adapter #17

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Empty file modified .husky/pre-commit
100755 → 100644
Empty file.
2 changes: 1 addition & 1 deletion lib/contracts
2 changes: 1 addition & 1 deletion lib/nitro
Submodule nitro updated 569 files
2 changes: 1 addition & 1 deletion lib/solidity-stringutils
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,8 @@
"src/**",
"types/**",
"out/**"
]
],
"dependencies": {
"@hyperlane-xyz/core": "^3.6.0"
}
}
202 changes: 202 additions & 0 deletions src/hyperlane-adapter/HyperlaneReceiverAdapterV3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.16;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IMailbox } from "./interfaces/IMailbox.sol";
import { IMessageRecipient } from "./interfaces/IMessageRecipient.sol";
import { IInterchainSecurityModule, ISpecifiesInterchainSecurityModule } from "./interfaces/IInterchainSecurityModule.sol";
import { TypeCasts } from "./libraries/TypeCasts.sol";
import { EncodeDecodeUtil } from "./libraries/EncodeDecodeUtil.sol";
import { Errors } from "./libraries/Errors.sol";
import { IMessageDispatcher } from "../interfaces/IMessageDispatcher.sol";
import { IMessageExecutor } from "../interfaces/IMessageExecutor.sol";
import "../libraries/MessageLib.sol";

/**
* @title HyperlaneReceiverAdapter implementation.
* @notice `IBridgeReceiverAdapter` implementation that uses Hyperlane as the bridge.
*/
contract HyperlaneReceiverAdapterV3 is
IMessageExecutor,
IMessageRecipient,
ISpecifiesInterchainSecurityModule,
Ownable
{
/// @notice `Mailbox` contract reference.
IMailbox public immutable mailbox;

/// @notice last message sender address
bytes32 public lastSender;

/// @notice last message received
bytes public lastMessage;

/// @notice `ISM` contract reference.
IInterchainSecurityModule public ism;

/**
* @notice Sender adapter address for each source chain.
* @dev srcChainId => senderAdapter address.
*/
mapping(uint256 => IMessageDispatcher) public senderAdapters;

/**
* @notice Ensure that messages cannot be replayed once they have been executed.
* @dev msgId => isExecuted.
*/
mapping(bytes32 => bool) public executedMessages;

/**
* @notice Emitted when the ISM is set.
* @param module The new ISM for this adapter/recipient.
*/
event IsmSet(address indexed module);

/**
* @notice Emitted when a messageId has already been executed.
* @param messageId ID uniquely identifying the message or message batch that were re-executed
*/
error MessageIdAlreadyExecuted(bytes32 messageId);

/**
* @notice Emitted when a sender adapter for a source chain is updated.
* @param srcChainId Source chain identifier.
* @param senderAdapter Address of the sender adapter.
*/
event SenderAdapterUpdated(uint256 srcChainId, IMessageDispatcher senderAdapter);

/* Constructor */
/**
* @notice HyperlaneReceiverAdapter constructor.
* @param _mailbox Address of the Hyperlane `Mailbox` contract.
*/
constructor(address _mailbox) {
if (_mailbox == address(0)) {
revert Errors.InvalidMailboxZeroAddress();
}
mailbox = IMailbox(_mailbox);
}

/// @notice Restrict access to trusted `Mailbox` contract.
modifier onlyMailbox() {
if (msg.sender != address(mailbox)) {
revert Errors.UnauthorizedMailbox(msg.sender);
}
_;
}

/// @inheritdoc ISpecifiesInterchainSecurityModule
function interchainSecurityModule() external view returns (IInterchainSecurityModule) {
return ism;
}

/**
* @notice Sets the ISM for this adapter/recipient.
* @param _ism The ISM contract address.
*/
function setIsm(address _ism) external onlyOwner {
ism = IInterchainSecurityModule(_ism);
emit IsmSet(_ism);
}

/**
* @notice Called by Hyperlane `Mailbox` contract on destination chain to receive cross-chain messages.
* @dev _origin Source chain domain identifier (not currently used).
* @param _sender Address of the sender on the source chain.
* @param _body Body of the message.
*/
function handle(
uint32 _origin,
bytes32 _sender,
bytes memory _body
) external payable onlyMailbox {
address adapter = TypeCasts.bytes32ToAddress(_sender);
//bool _executedMessageId;
(
MessageLib.Message[] memory _messages,
bytes32 msgId,
uint256 srcChainId,
address srcSender
) = EncodeDecodeUtil.decode(_body);

if (_origin != srcChainId) {
revert Errors.UnauthorizedOrigin(_origin);
}

if (IMessageDispatcher(adapter) != senderAdapters[srcChainId]) {
revert Errors.UnauthorizedAdapter(srcChainId, adapter);
}

if (_messages.length < 1) {
revert Errors.NoMessagesSent(srcChainId);
}

if (executedMessages[msgId]) {
revert MessageIdAlreadyExecuted(msgId);
}

if (_messages.length == 1) {
MessageLib.Message memory _message = _messages[0];
executeMessage(_message.to, _message.data, msgId, srcChainId, srcSender);
} else {
executeMessageBatch(
_messages,
msgId,
srcChainId,
srcSender
// _executedMessageId
);
}

lastSender = _sender;
lastMessage = _body;
}

function executeMessage(
address _to,
bytes memory _message,
bytes32 _messageId,
uint256 _fromChainId,
address _from
) public override onlyMailbox {
bool _executedMessageId = executedMessages[_messageId];
executedMessages[_messageId] = true;

MessageLib.executeMessage(_to, _message, _messageId, _fromChainId, _from, _executedMessageId);

emit MessageIdExecuted(_fromChainId, _messageId);
}

function updateSenderAdapter(
uint256[] calldata _srcChainIds,
IMessageDispatcher[] calldata _senderAdapters
) external onlyOwner {
if (_srcChainIds.length != _senderAdapters.length) {
revert Errors.MismatchChainsAdaptersLength(_srcChainIds.length, _senderAdapters.length);
}
for (uint256 i; i < _srcChainIds.length; ++i) {
senderAdapters[_srcChainIds[i]] = _senderAdapters[i];
emit SenderAdapterUpdated(_srcChainIds[i], _senderAdapters[i]);
}
}

function executeMessageBatch(
MessageLib.Message[] memory _messages,
bytes32 _messageId,
uint256 _fromChainId,
address _from // bool _executedMessageId
) public override onlyMailbox {

bool _executedMessageId = executedMessages[_messageId];
executedMessages[_messageId] = true;

MessageLib.executeMessageBatch(_messages, _messageId, _fromChainId, _from, _executedMessageId);

emit MessageIdExecuted(_fromChainId, _messageId);
}

function getSenderAdapter(
uint256 _srcChainId
) public view returns (IMessageDispatcher _senderAdapter) {
_senderAdapter = senderAdapters[_srcChainId];
}
}
Loading