forked from pooltogether/ERC5164
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEthereumToOptimismDispatcher.sol
162 lines (129 loc) · 5.6 KB
/
EthereumToOptimismDispatcher.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.16;
import { ICrossDomainMessenger } from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol";
import { IMessageExecutor } from "../interfaces/IMessageExecutor.sol";
import { IMessageDispatcher, ISingleMessageDispatcher } from "../interfaces/ISingleMessageDispatcher.sol";
import { IBatchedMessageDispatcher } from "../interfaces/IBatchedMessageDispatcher.sol";
import "../libraries/MessageLib.sol";
/**
* @title MessageDispatcherOptimism contract
* @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 {
/* ============ Variables ============ */
/// @notice Address of the Optimism cross domain messenger on the Ethereum chain.
ICrossDomainMessenger public immutable crossDomainMessenger;
/// @notice Address of the executor contract on the Optimism chain.
IMessageExecutor internal executor;
/// @notice Nonce used to compute unique `messageId`s.
uint256 internal nonce;
/// @notice ID of the chain receiving the dispatched messages. i.e.: 10 for Mainnet, 420 for Goerli.
uint256 internal immutable toChainId;
/// @notice Free gas limit on Optimism
uint32 internal constant GAS_LIMIT = uint32(1920000);
/* ============ Constructor ============ */
/**
* @notice MessageDispatcherOptimism constructor.
* @param _crossDomainMessenger Address of the Optimism cross domain messenger
* @param _toChainId ID of the chain receiving the dispatched messages
*/
constructor(ICrossDomainMessenger _crossDomainMessenger, uint256 _toChainId) {
require(address(_crossDomainMessenger) != address(0), "Dispatcher/CDM-not-zero-address");
require(_toChainId != 0, "Dispatcher/chainId-not-zero");
crossDomainMessenger = _crossDomainMessenger;
toChainId = _toChainId;
}
/* ============ External Functions ============ */
/// @inheritdoc ISingleMessageDispatcher
function dispatchMessage(
uint256 _toChainId,
address _to,
bytes calldata _data
) external returns (bytes32) {
address _executorAddress = _getMessageExecutorAddress(_toChainId);
_checkExecutor(_executorAddress);
uint256 _nonce = _incrementNonce();
bytes32 _messageId = MessageLib.computeMessageId(_nonce, msg.sender, _to, _data);
_sendMessage(
_executorAddress,
MessageLib.encodeMessage(_to, _data, _messageId, block.chainid, msg.sender)
);
emit MessageDispatched(_messageId, msg.sender, _toChainId, _to, _data);
return _messageId;
}
/// @inheritdoc IBatchedMessageDispatcher
function dispatchMessageBatch(uint256 _toChainId, MessageLib.Message[] calldata _messages)
external
returns (bytes32)
{
address _executorAddress = _getMessageExecutorAddress(_toChainId);
_checkExecutor(_executorAddress);
uint256 _nonce = _incrementNonce();
bytes32 _messageId = MessageLib.computeMessageBatchId(_nonce, msg.sender, _messages);
_sendMessage(
_executorAddress,
MessageLib.encodeMessageBatch(_messages, _messageId, block.chainid, msg.sender)
);
emit MessageBatchDispatched(_messageId, msg.sender, _toChainId, _messages);
return _messageId;
}
/// @inheritdoc IMessageDispatcher
function getMessageExecutorAddress(uint256 _toChainId) external view returns (address) {
return _getMessageExecutorAddress(_toChainId);
}
/**
* @notice Set executor contract address.
* @dev Will revert if it has already been set.
* @param _executor Address of the executor contract on the Optimism chain
*/
function setExecutor(IMessageExecutor _executor) external {
require(address(executor) == address(0), "Dispatcher/executor-already-set");
executor = _executor;
}
/* ============ Internal Functions ============ */
/**
* @notice Check toChainId to ensure messages can be dispatched to this chain.
* @dev Will revert if `_toChainId` is not supported.
* @param _toChainId ID of the chain receiving the message
*/
function _checkToChainId(uint256 _toChainId) internal view {
require(_toChainId == toChainId, "Dispatcher/chainId-not-supported");
}
/**
* @notice Check dispatch parameters to ensure messages can be dispatched.
* @dev Will revert if `executor` is not set.
* @param _executor Address of the executor contract on the Optimism chain
*/
function _checkExecutor(address _executor) internal pure {
require(_executor != address(0), "Dispatcher/executor-not-set");
}
/**
* @notice Retrieves address of the MessageExecutor contract on the receiving chain.
* @dev Will revert if `_toChainId` is not supported.
* @param _toChainId ID of the chain with which MessageDispatcher is communicating
* @return address MessageExecutor contract address
*/
function _getMessageExecutorAddress(uint256 _toChainId) internal view returns (address) {
_checkToChainId(_toChainId);
return address(executor);
}
/**
* @notice Helper to increment nonce.
* @return uint256 Incremented nonce
*/
function _incrementNonce() internal returns (uint256) {
unchecked {
nonce++;
}
return nonce;
}
/**
* @notice Dispatch message to Optimism chain.
* @param _executor Address of the executor contract on the Optimism chain
* @param _message Message dispatched
*/
function _sendMessage(address _executor, bytes memory _message) internal {
crossDomainMessenger.sendMessage(_executor, _message, GAS_LIMIT);
}
}