-
Notifications
You must be signed in to change notification settings - Fork 32
/
MessageRecipient.sol
119 lines (109 loc) · 5.1 KB
/
MessageRecipient.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
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
// ══════════════════════════════ LIBRARY IMPORTS ══════════════════════════════
import {
CallerNotDestination,
IncorrectNonce,
IncorrectSender,
IncorrectRecipient,
ZeroProofMaturity
} from "../libs/Errors.sol";
import {Request, RequestLib} from "../libs/stack/Request.sol";
// ═════════════════════════════ INTERNAL IMPORTS ══════════════════════════════
import {InterfaceOrigin} from "../interfaces/InterfaceOrigin.sol";
import {IMessageRecipient} from "../interfaces/IMessageRecipient.sol";
abstract contract MessageRecipient is IMessageRecipient {
struct MessageRequest {
uint96 gasDrop;
uint64 gasLimit;
uint32 version;
}
/// @notice Local chain Origin: used for sending messages
address public immutable origin;
/// @notice Local chain Destination: used for receiving messages
address public immutable destination;
constructor(address origin_, address destination_) {
origin = origin_;
destination = destination_;
}
/// @inheritdoc IMessageRecipient
function receiveBaseMessage(
uint32 origin_,
uint32 nonce,
bytes32 sender,
uint256 proofMaturity,
uint32 version,
bytes memory content
) external payable {
if (msg.sender != destination) revert CallerNotDestination();
if (nonce == 0) revert IncorrectNonce();
if (sender == 0) revert IncorrectSender();
if (proofMaturity == 0) revert ZeroProofMaturity();
_receiveBaseMessageUnsafe(origin_, nonce, sender, proofMaturity, version, content);
}
/**
* @dev Child contracts should implement the logic for receiving a Base Message in an "unsafe way".
* Following checks HAVE been performed:
* - receiveBaseMessage() was called by Destination (i.e. this is a legit base message).
* - Nonce is not zero.
* - Message sender on origin chain is not a zero address.
* - Proof maturity is not zero.
* Following checks HAVE NOT been performed (thus "unsafe"):
* - Message sender on origin chain could be anything non-zero at this point.
* - Proof maturity could be anything non-zero at this point.
*/
function _receiveBaseMessageUnsafe(
uint32 origin_,
uint32 nonce,
bytes32 sender,
uint256 proofMaturity,
uint32 version,
bytes memory content
) internal virtual;
/**
* @dev Sends a message to given destination chain. Full `msg.value` is used to pay for the message tips.
* `_getMinimumTipsValue()` could be used to calculate the minimum required tips value, and should be also
* exposed as a public view function to estimate the tips value before sending a message off-chain.
* This function is not exposed in MessageRecipient, as the message encoding is implemented by the child contract.
* @param destination_ Domain of the destination chain
* @param recipient Address of the recipient on destination chain
* @param optimisticPeriod Optimistic period for the message
* @param tipsValue Tips to be paid for sending the message
* @param request Message execution request on destination chain
* @param content The message content
*/
function _sendBaseMessage(
uint32 destination_,
bytes32 recipient,
uint32 optimisticPeriod,
uint256 tipsValue,
MessageRequest memory request,
bytes memory content
) internal returns (uint32 messageNonce, bytes32 messageHash) {
if (recipient == 0) revert IncorrectRecipient();
return InterfaceOrigin(origin).sendBaseMessage{value: tipsValue}(
destination_, recipient, optimisticPeriod, _encodeRequest(request), content
);
}
/**
* @dev Returns the minimum tips value for sending a message to given destination chain.
* @param destination_ Domain of the destination chain
* @param request Message execution request on destination chain
* @param contentLength Length of the message content
*/
function _getMinimumTipsValue(uint32 destination_, MessageRequest memory request, uint256 contentLength)
internal
view
returns (uint256 tipsValue)
{
return InterfaceOrigin(origin).getMinimumTipsValue(destination_, _encodeRequest(request), contentLength);
}
/**
* @dev Encodes a message execution request into format that Origin contract is using.
* @param request Message execution request on destination chain
* @return paddedRequest Encoded request
*/
function _encodeRequest(MessageRequest memory request) internal pure returns (uint256 paddedRequest) {
return Request.unwrap(RequestLib.encodeRequest(request.gasDrop, request.gasLimit, request.version));
}
}