Skip to content

Commit

Permalink
feat(ethereumToArb): add dispatchAndProcess fns
Browse files Browse the repository at this point in the history
  • Loading branch information
PierrickGT committed Oct 30, 2023
1 parent 9cfb405 commit 553781e
Show file tree
Hide file tree
Showing 11 changed files with 512 additions and 167 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ For most bridges, you only have to call `dispatchMessage` or `dispatchMessageBat

### Dispatch a message

To dispatch a message from Ethereum to the L2 of your choice, you have to interact with the [ISingleMessageDispatcher](./src/interfaces/ISingleMessageDispatcher.sol) contract and call the following function.
To dispatch a message from Ethereum to the L2 of your choice, you have to interact with the [IMessageDispatcher](./src/interfaces/IMessageDispatcher.sol) contract and call the following function.

```solidity
/**
Expand All @@ -58,7 +58,7 @@ function dispatchMessage(

### Dispatch a batch messages

To dispatch a batch of messages from Ethereum to the L2 of your choice, you have to interact with the [IBatchedMessageDispatcher](./src/interfaces/IBatchedMessageDispatcher.sol) contract and call the following function.
To dispatch a batch of messages from Ethereum to the L2 of your choice, you have to interact with the [IBatchMessageDispatcher](./src/interfaces/IBatchMessageDispatcher.sol) contract and call the following function.

```solidity
/**
Expand Down
184 changes: 122 additions & 62 deletions src/ethereum-arbitrum/EthereumToArbitrumDispatcher.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.16;

import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol";

import { IMessageDispatcher } from "../interfaces/IMessageDispatcher.sol";
import { IMessageExecutor } from "../interfaces/IMessageExecutor.sol";
import { ISingleMessageDispatcher } from "../interfaces/ISingleMessageDispatcher.sol";
import { IBatchedMessageDispatcher } from "../interfaces/IBatchedMessageDispatcher.sol";
import { IMessageDispatcher, IBatchMessageDispatcher, IMessageDispatcherArbitrum } from "../interfaces/IMessageDispatcherArbitrum.sol";

import { MessageLib } from "../libraries/MessageLib.sol";

Expand All @@ -16,35 +13,7 @@ import { MessageLib } from "../libraries/MessageLib.sol";
* @notice The MessageDispatcherArbitrum contract allows a user or contract to send messages from Ethereum to Arbitrum.
* It lives on the Ethereum chain and communicates with the `MessageExecutorArbitrum` contract on the Arbitrum chain.
*/
contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageDispatcher {
/* ============ Events ============ */

/**
* @notice Emitted once a message has been processed and put in the Arbitrum inbox.
* @dev Using the `ticketId`, this message can be reexecuted for some fixed amount of time if it reverts.
* @param messageId ID uniquely identifying the messages
* @param sender Address who processed the messages
* @param ticketId Id of the newly created retryable ticket
*/
event MessageProcessed(
bytes32 indexed messageId,
address indexed sender,
uint256 indexed ticketId
);

/**
* @notice Emitted once a message has been processed and put in the Arbitrum inbox.
* @dev Using the `ticketId`, this message can be reexecuted for some fixed amount of time if it reverts.
* @param messageId ID uniquely identifying the messages
* @param sender Address who processed the messages
* @param ticketId Id of the newly created retryable ticket
*/
event MessageBatchProcessed(
bytes32 indexed messageId,
address indexed sender,
uint256 indexed ticketId
);

contract MessageDispatcherArbitrum is IMessageDispatcherArbitrum {
/* ============ Variables ============ */

/// @notice Address of the Arbitrum inbox on the Ethereum chain.
Expand Down Expand Up @@ -83,16 +52,15 @@ contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageD

/* ============ External Functions ============ */

/// @inheritdoc ISingleMessageDispatcher
/// @inheritdoc IMessageDispatcher
function dispatchMessage(
uint256 _toChainId,
address _to,
bytes calldata _data
) external returns (bytes32) {
_checkToChainId(_toChainId);

uint256 _nonce = _incrementNonce();
bytes32 _messageId = MessageLib.computeMessageId(_nonce, msg.sender, _to, _data);
bytes32 _messageId = _computeMessageId(msg.sender, _to, _data);

dispatched[_getMessageTxHash(_messageId, msg.sender, _to, _data)] = true;

Expand All @@ -101,15 +69,14 @@ contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageD
return _messageId;
}

/// @inheritdoc IBatchedMessageDispatcher
/// @inheritdoc IBatchMessageDispatcher
function dispatchMessageBatch(
uint256 _toChainId,
MessageLib.Message[] calldata _messages
) external returns (bytes32) {
_checkToChainId(_toChainId);

uint256 _nonce = _incrementNonce();
bytes32 _messageId = MessageLib.computeMessageBatchId(_nonce, msg.sender, _messages);
bytes32 _messageId = _computeMessageBatchId(msg.sender, _messages);

dispatched[_getMessageBatchTxHash(_messageId, msg.sender, _messages)] = true;

Expand All @@ -119,19 +86,10 @@ contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageD
}

/**
* @notice Process message that has been dispatched.
* @inheritdoc IMessageDispatcherArbitrum
* @dev The transaction hash must match the one stored in the `dispatched` mapping.
* @dev `_from` is passed as `callValueRefundAddress` cause this address can cancel the retryably ticket.
* @dev We store `_message` in memory to avoid a stack too deep error.
* @param _messageId ID of the message to process
* @param _from Address who dispatched the `_data`
* @param _to Address that will receive the message
* @param _data Data that was dispatched
* @param _refundAddress Address that will receive the `excessFeeRefund` amount if any
* @param _gasLimit Maximum amount of gas required for the `_messages` to be executed
* @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param _gasPriceBid Gas price bid for L2 execution
* @return uint256 Id of the retryable ticket that was created
* @dev `from` is passed as `messageValueRefundAddress` cause this address can cancel the retryably ticket.
* @dev We store `message` in memory to avoid a stack too deep error.
*/
function processMessage(
bytes32 _messageId,
Expand Down Expand Up @@ -169,18 +127,10 @@ contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageD
}

/**
* @notice Process messages that have been dispatched.
* @inheritdoc IMessageDispatcherArbitrum
* @dev The transaction hash must match the one stored in the `dispatched` mapping.
* @dev `_from` is passed as `messageValueRefundAddress` cause this address can cancel the retryably ticket.
* @dev We store `_message` in memory to avoid a stack too deep error.
* @param _messageId ID of the messages to process
* @param _messages Array of messages being processed
* @param _from Address who dispatched the `_messages`
* @param _refundAddress Address that will receive the `excessFeeRefund` amount if any
* @param _gasLimit Maximum amount of gas required for the `_messages` to be executed
* @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param _gasPriceBid Gas price bid for L2 execution
* @return uint256 Id of the retryable ticket that was created
* @dev `from` is passed as `messageValueRefundAddress` cause this address can cancel the retryably ticket.
* @dev We store `messageBatch` in memory to avoid a stack too deep error.
*/
function processMessageBatch(
bytes32 _messageId,
Expand Down Expand Up @@ -221,6 +171,90 @@ contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageD
return _ticketID;
}

/**
* @inheritdoc IMessageDispatcherArbitrum
* @dev `_from` is passed as `callValueRefundAddress` cause this address can cancel the retryably ticket.
* @dev We store `_message` in memory to avoid a stack too deep error.
*/
function dispatchAndProcessMessage(
uint256 _toChainId,
address _to,
bytes calldata _data,
address _refundAddress,
uint256 _gasLimit,
uint256 _maxSubmissionCost,
uint256 _gasPriceBid
) external payable returns (uint256 ticketId) {
address _executorAddress = address(executor);
_checkProcessParams(_executorAddress, _refundAddress);
_checkToChainId(_toChainId);

bytes32 _messageId = _computeMessageId(msg.sender, _to, _data);
bytes memory _message = MessageLib.encodeMessage(
_to,
_data,
_messageId,
block.chainid,
msg.sender
);

ticketId = _createRetryableTicket(
_executorAddress,
_maxSubmissionCost,
_refundAddress,
msg.sender,
_gasLimit,
_gasPriceBid,
_message
);

emit MessageDispatchedAndProcessed(_messageId, msg.sender, _toChainId, _to, _data, ticketId);
}

/**
* @inheritdoc IMessageDispatcherArbitrum
* @dev `_from` is passed as `callValueRefundAddress` cause this address can cancel the retryably ticket.
* @dev We store `_messageBatch` in memory to avoid a stack too deep error.
*/
function dispatchAndProcessMessageBatch(
uint256 _toChainId,
MessageLib.Message[] calldata _messages,
address _refundAddress,
uint256 _gasLimit,
uint256 _maxSubmissionCost,
uint256 _gasPriceBid
) external payable returns (uint256 ticketId) {
address _executorAddress = address(executor);
_checkProcessParams(_executorAddress, _refundAddress);
_checkToChainId(_toChainId);

bytes32 _messageId = _computeMessageBatchId(msg.sender, _messages);
bytes memory _messageBatch = MessageLib.encodeMessageBatch(
_messages,
_messageId,
block.chainid,
msg.sender
);

ticketId = _createRetryableTicket(
_executorAddress,
_maxSubmissionCost,
_refundAddress,
msg.sender,
_gasLimit,
_gasPriceBid,
_messageBatch
);

emit MessageBatchDispatchedAndProcessed(
_messageId,
msg.sender,
_toChainId,
_messages,
ticketId
);
}

/**
* @notice Set executor contract address.
* @dev Will revert if it has already been set.
Expand Down Expand Up @@ -340,6 +374,32 @@ contract MessageDispatcherArbitrum is ISingleMessageDispatcher, IBatchedMessageD
return nonce;
}

/**
* @notice Compute message id.
* @param _from Address that dispatched the message
* @param _to Address that will receive the message
* @param _data Data to dispatch
*/
function _computeMessageId(
address _from,
address _to,
bytes calldata _data
) internal returns (bytes32) {
return MessageLib.computeMessageId(_incrementNonce(), _from, _to, _data);
}

/**
* @notice Compute message batch id.
* @param _from Address that dispatched the batch of messages
* @param _messages Array of Message to dispatch
*/
function _computeMessageBatchId(
address _from,
MessageLib.Message[] memory _messages
) internal returns (bytes32) {
return MessageLib.computeMessageBatchId(_incrementNonce(), _from, _messages);
}

/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev all msg.value will be deposited to `_callValueRefundAddress` on L2
Expand Down
30 changes: 6 additions & 24 deletions src/ethereum-optimism/EthereumToOptimismDispatcher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ pragma solidity ^0.8.16;
import { ICrossDomainMessenger } from "../vendor/optimism/ICrossDomainMessenger.sol";

import { IMessageExecutor } from "../interfaces/IMessageExecutor.sol";
import { IMessageDispatcher, ISingleMessageDispatcher } from "../interfaces/ISingleMessageDispatcher.sol";
import { IBatchedMessageDispatcher } from "../interfaces/IBatchedMessageDispatcher.sol";
import { IMessageDispatcher, IBatchMessageDispatcher, IMessageDispatcherOptimism } from "../interfaces/IMessageDispatcherOptimism.sol";

import { MessageLib } from "../libraries/MessageLib.sol";

Expand All @@ -14,7 +13,7 @@ import { MessageLib } from "../libraries/MessageLib.sol";
* @notice The MessageDispatcherOptimism contract allows a user or contract to send messages from Ethereum to Optimism.
* It lives on the Ethereum chain and communicates with the `MessageExecutorOptimism` contract on the Optimism chain.
*/
contract MessageDispatcherOptimism is ISingleMessageDispatcher, IBatchedMessageDispatcher {
contract MessageDispatcherOptimism is IMessageDispatcherOptimism {
/* ============ Variables ============ */

/// @notice Address of the Optimism cross domain messenger on the Ethereum chain.
Expand Down Expand Up @@ -51,7 +50,7 @@ contract MessageDispatcherOptimism is ISingleMessageDispatcher, IBatchedMessageD

/* ============ External Functions ============ */

/// @inheritdoc ISingleMessageDispatcher
/// @inheritdoc IMessageDispatcher
function dispatchMessage(
uint256 _toChainId,
address _to,
Expand All @@ -60,16 +59,7 @@ contract MessageDispatcherOptimism is ISingleMessageDispatcher, IBatchedMessageD
return _dispatchMessage(_toChainId, _to, _data, gasLimit);
}

/**
* @notice Dispatch and process a message to the receiving chain.
* @dev Must compute and return an ID uniquely identifying the message.
* @dev Must emit the `MessageDispatched` event when successfully dispatched.
* @param _toChainId ID of the receiving chain
* @param _to Address on the receiving chain that will receive `data`
* @param _data Data dispatched to the receiving chain
* @param _gasLimit Gas limit at which the message will be executed on Optimism
* @return bytes32 ID uniquely identifying the message
*/
/// @inheritdoc IMessageDispatcherOptimism
function dispatchMessageWithGasLimit(
uint256 _toChainId,
address _to,
Expand All @@ -79,23 +69,15 @@ contract MessageDispatcherOptimism is ISingleMessageDispatcher, IBatchedMessageD
return _dispatchMessage(_toChainId, _to, _data, _gasLimit);
}

/// @inheritdoc IBatchedMessageDispatcher
/// @inheritdoc IBatchMessageDispatcher
function dispatchMessageBatch(
uint256 _toChainId,
MessageLib.Message[] calldata _messages
) external returns (bytes32) {
return _dispatchMessageBatch(_toChainId, _messages, gasLimit);
}

/**
* @notice Dispatch and process `messages` to the receiving chain.
* @dev Must compute and return an ID uniquely identifying the `messages`.
* @dev Must emit the `MessageBatchDispatched` event when successfully dispatched.
* @param _toChainId ID of the receiving chain
* @param _messages Array of Message dispatched
* @param _gasLimit Gas limit at which the message will be executed on Optimism
* @return bytes32 ID uniquely identifying the `messages`
*/
/// @inheritdoc IMessageDispatcherOptimism
function dispatchMessageWithGasLimitBatch(
uint256 _toChainId,
MessageLib.Message[] calldata _messages,
Expand Down
13 changes: 4 additions & 9 deletions src/ethereum-polygon/EthereumToPolygonDispatcher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ pragma solidity ^0.8.16;

import { FxBaseRootTunnel } from "@maticnetwork/fx-portal/contracts/tunnel/FxBaseRootTunnel.sol";

import { IMessageDispatcher, ISingleMessageDispatcher } from "../interfaces/ISingleMessageDispatcher.sol";
import { IBatchedMessageDispatcher } from "../interfaces/IBatchedMessageDispatcher.sol";
import { IMessageDispatcher, IBatchMessageDispatcher } from "../interfaces/IBatchMessageDispatcher.sol";

import { MessageLib } from "../libraries/MessageLib.sol";

Expand All @@ -14,11 +13,7 @@ import { MessageLib } from "../libraries/MessageLib.sol";
* @notice The MessageDispatcherPolygon contract allows a user or contract to send messages from Ethereum to Polygon.
* It lives on the Ethereum chain and communicates with the `MessageExecutorPolygon` contract on the Polygon chain.
*/
contract MessageDispatcherPolygon is
ISingleMessageDispatcher,
IBatchedMessageDispatcher,
FxBaseRootTunnel
{
contract MessageDispatcherPolygon is IBatchMessageDispatcher, FxBaseRootTunnel {
/* ============ Variables ============ */

/// @notice Nonce used to compute unique `messageId`s.
Expand Down Expand Up @@ -46,7 +41,7 @@ contract MessageDispatcherPolygon is

/* ============ External Functions ============ */

/// @inheritdoc ISingleMessageDispatcher
/// @inheritdoc IMessageDispatcher
function dispatchMessage(
uint256 _toChainId,
address _to,
Expand All @@ -67,7 +62,7 @@ contract MessageDispatcherPolygon is
return _messageId;
}

/// @inheritdoc IBatchedMessageDispatcher
/// @inheritdoc IBatchMessageDispatcher
function dispatchMessageBatch(
uint256 _toChainId,
MessageLib.Message[] calldata _messages
Expand Down
Loading

0 comments on commit 553781e

Please sign in to comment.