-
Notifications
You must be signed in to change notification settings - Fork 6
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
2224532
41c447a
787c755
8ac5460
73a1fb9
9bdd08b
7879ac5
d778c87
17d4ebd
57b4df8
fad1b72
9bf2e93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,16 +6,17 @@ 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"; | ||
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 HyperlaneReceiverAdapter is | ||
contract HyperlaneReceiverAdapterV2 is | ||
IMessageRecipient, | ||
ISpecifiesInterchainSecurityModule, | ||
Ownable | ||
|
@@ -130,8 +131,7 @@ contract HyperlaneReceiverAdapter is | |
* @param _body Body of the message. | ||
*/ | ||
function handle( | ||
uint32, | ||
/* _origin*/ | ||
uint32 _origin, | ||
bytes32 _sender, | ||
bytes memory _body | ||
) external onlyMailbox { | ||
|
@@ -142,20 +142,27 @@ contract HyperlaneReceiverAdapter is | |
bytes32 msgId, | ||
uint256 srcChainId, | ||
address srcSender | ||
) = abi.decode(_body, (MessageLib.Message[], bytes32, uint256, address)); | ||
) = EncodeDecodeUtil.decode(_body); | ||
|
||
if (_origin != srcChainId) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comparing the origin and sender chain |
||
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); | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did all my revert conditions up front and did state changes after |
||
_executedMessageId = executedMessages[msgId]; | ||
executedMessages[msgId] = true; | ||
} | ||
if (_messages.length < 1) { | ||
revert Errors.NoMessagesSent(srcChainId); | ||
} | ||
|
||
if (_messages.length == 1) { | ||
MessageLib.Message memory _message = _messages[0]; | ||
executeMessage(_message.to, _message.data, msgId, srcChainId, srcSender, _executedMessageId); | ||
|
@@ -177,9 +184,11 @@ contract HyperlaneReceiverAdapter is | |
} | ||
} | ||
|
||
function getSenderAdapter( | ||
uint256 _srcChainId | ||
) public view returns (IMessageDispatcher _senderAdapter) { | ||
function getSenderAdapter(uint256 _srcChainId) | ||
public | ||
view | ||
returns (IMessageDispatcher _senderAdapter) | ||
{ | ||
_senderAdapter = senderAdapters[_srcChainId]; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,11 +7,12 @@ import { IInterchainGasPaymaster } from "./interfaces/IInterchainGasPaymaster.so | |
import { TypeCasts } from "./libraries/TypeCasts.sol"; | ||
import { Errors } from "./libraries/Errors.sol"; | ||
import { IMessageDispatcher, ISingleMessageDispatcher } from "./interfaces/ISingleMessageDispatcher.sol"; | ||
import { EncodeDecodeUtil } from "./libraries/EncodeDecodeUtil.sol"; | ||
import { IBatchedMessageDispatcher } from "./interfaces/IBatchedMessageDispatcher.sol"; | ||
import { IMessageExecutor } from "./interfaces/IMessageExecutor.sol"; | ||
import "./libraries/MessageLib.sol"; | ||
import { IMessageExecutor } from "../interfaces/IMessageExecutor.sol"; | ||
import "../libraries/MessageLib.sol"; | ||
|
||
contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDispatcher, Ownable { | ||
contract HyperlaneSenderAdapterV2 is ISingleMessageDispatcher, IBatchedMessageDispatcher, Ownable { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated to V2 |
||
/// @notice `Mailbox` contract reference. | ||
IMailbox public immutable mailbox; | ||
|
||
|
@@ -20,6 +21,8 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
|
||
uint256 public nonce; | ||
|
||
uint256 public immutable gasAmount; | ||
|
||
/** | ||
* @notice Receiver adapter address for each destination chain. | ||
* @dev dstChainId => receiverAdapter address. | ||
|
@@ -58,10 +61,18 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
* @notice HyperlaneSenderAdapter constructor. | ||
* @param _mailbox Address of the Hyperlane `Mailbox` contract. | ||
*/ | ||
constructor(address _mailbox, address _igp) { | ||
constructor( | ||
address _mailbox, | ||
address _igp, | ||
uint256 _gasAmount | ||
) { | ||
if (_mailbox == address(0)) { | ||
revert Errors.InvalidMailboxZeroAddress(); | ||
} | ||
|
||
// See https://docs.hyperlane.xyz/docs/build-with-hyperlane/guides/paying-for-interchain-gas | ||
// Set gasAmount to the default (500,000) if _gasAmount is 0 | ||
gasAmount = (_gasAmount == 0) ? 500000 : _gasAmount; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. made gasAmount a configurable option in the constructor, it it isn't set (set to zero), it defaults to 500k |
||
mailbox = IMailbox(_mailbox); | ||
_setIgp(_igp); | ||
} | ||
|
@@ -75,12 +86,10 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
bytes calldata /* data*/ | ||
) external view returns (uint256) { | ||
uint32 dstDomainId = _getDestinationDomain(toChainId); | ||
// destination gasAmount is hardcoded to 500k similar to Wormhole implementation | ||
// See https://docs.hyperlane.xyz/docs/build-with-hyperlane/guides/paying-for-interchain-gas | ||
try igp.quoteGasPayment(dstDomainId, 500000) returns (uint256 gasQuote) { | ||
try igp.quoteGasPayment(dstDomainId, gasAmount) returns (uint256 gasQuote) { | ||
return gasQuote; | ||
} catch { | ||
// Default to zero, MultiMessageSender.estimateTotalMessageFee doesn't expect this function to revert | ||
return 0; | ||
} | ||
} | ||
|
@@ -112,7 +121,7 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
MessageLib.Message[] memory _messages = new MessageLib.Message[](1); | ||
_messages[0] = MessageLib.Message({ to: _to, data: _data }); | ||
|
||
bytes memory payload = abi.encode(_messages, msgId, block.chainid, msg.sender); | ||
bytes memory payload = EncodeDecodeUtil.encode(_messages, msgId, block.chainid, msg.sender); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Used the library I created for encoding/decoding to encode the messages with extra relevant data to generate a payload |
||
|
||
bytes32 hyperlaneMsgId = IMailbox(mailbox).dispatch( | ||
dstDomainId, | ||
|
@@ -122,26 +131,20 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
); | ||
|
||
// try to make gas payment, ignore failures | ||
// destination gasAmount is hardcoded to 500k similar to Wormhole implementation | ||
// refundAddress is set from MMS caller state variable | ||
try | ||
igp.payForGas{ value: msg.value }( | ||
hyperlaneMsgId, | ||
dstDomainId, | ||
500000, | ||
//address(this) | ||
msg.sender | ||
) | ||
igp.payForGas{ value: msg.value }(hyperlaneMsgId, dstDomainId, gasAmount, msg.sender) | ||
{} catch {} | ||
|
||
emit MessageDispatched(msgId, msg.sender, _toChainId, _to, _data); | ||
return msgId; | ||
} | ||
|
||
function dispatchMessageBatch( | ||
uint256 _toChainId, | ||
MessageLib.Message[] calldata _messages | ||
) external payable override returns (bytes32) { | ||
function dispatchMessageBatch(uint256 _toChainId, MessageLib.Message[] calldata _messages) | ||
external | ||
payable | ||
override | ||
returns (bytes32) | ||
{ | ||
IMessageExecutor adapter = _getMessageExecutorAddress(_toChainId); | ||
_checkAdapter(_toChainId, adapter); | ||
uint32 dstDomainId = _getDestinationDomain(_toChainId); | ||
|
@@ -152,7 +155,7 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
|
||
uint256 _nonce = _incrementNonce(); | ||
bytes32 msgId = MessageLib.computeMessageBatchId(_nonce, msg.sender, _messages); | ||
bytes memory payload = abi.encode(_messages, msgId, block.chainid, msg.sender); | ||
bytes memory payload = EncodeDecodeUtil.encode(_messages, msgId, block.chainid, msg.sender); | ||
|
||
bytes32 hyperlaneMsgId = IMailbox(mailbox).dispatch( | ||
dstDomainId, | ||
|
@@ -162,16 +165,8 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
); | ||
|
||
// try to make gas payment, ignore failures | ||
// destination gasAmount is hardcoded to 500k similar to Wormhole implementation | ||
// refundAddress is set from MMS caller state variable | ||
try | ||
igp.payForGas{ value: msg.value }( | ||
hyperlaneMsgId, | ||
dstDomainId, | ||
500000, | ||
//address(this) | ||
msg.sender | ||
) | ||
igp.payForGas{ value: msg.value }(hyperlaneMsgId, dstDomainId, gasAmount, msg.sender) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved gas amount to storage as gas amount is now a state variable set in the constructor |
||
{} catch {} | ||
|
||
emit MessageBatchDispatched(msgId, msg.sender, _toChainId, _messages); | ||
|
@@ -201,9 +196,11 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
require(_executor == executor, "Dispatcher/executor-mis-match"); | ||
} | ||
|
||
function getMessageExecutorAddress( | ||
uint256 _toChainId | ||
) external view returns (address _executorAddress) { | ||
function getMessageExecutorAddress(uint256 _toChainId) | ||
external | ||
view | ||
returns (address _executorAddress) | ||
{ | ||
_executorAddress = address(_getMessageExecutorAddress(_toChainId)); | ||
} | ||
|
||
|
@@ -261,9 +258,11 @@ contract HyperlaneSenderAdapter is ISingleMessageDispatcher, IBatchedMessageDisp | |
* @param _toChainId ID of the chain with which MessageDispatcher is communicating | ||
* @return receiverAdapter MessageExecutor contract address | ||
*/ | ||
function _getMessageExecutorAddress( | ||
uint256 _toChainId | ||
) internal view returns (IMessageExecutor receiverAdapter) { | ||
function _getMessageExecutorAddress(uint256 _toChainId) | ||
internal | ||
view | ||
returns (IMessageExecutor receiverAdapter) | ||
{ | ||
_checkToChainId(_toChainId); | ||
receiverAdapter = receiverAdapters[_toChainId]; | ||
} | ||
|
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to V2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be v3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the adapter to use hyperlane V3 and added some unit tests as well