1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^ 0.8.20 ;
3
+ import "./wrapper/CCIPAllowlistedChain.sol " ;
4
+ import "./wrapper/CCIPReceiverDefensive.sol " ;
5
+ import "./internal/CCIPRouterManage.sol " ;
6
+ abstract contract CCIPBaseReceiver is CCIPAllowlistedChain , CCIPReceiverDefensive , CCIPRouterManage {
7
+ using EnumerableMap for EnumerableMap.Bytes32ToUintMap;
8
+ // Event emitted when a message is received from another chain.
9
+ /*event MessageReceived(
10
+ bytes32 indexed messageId, // The unique ID of the CCIP message.
11
+ uint64 indexed sourceChainSelector, // The chain selector of the source chain.
12
+ address sender, // The address of the sender from the source chain.
13
+ string text // The text that was received.
14
+ );*/
15
+ // Event emitted when a message is received from another chain.
16
+ event MessageReceived (
17
+ bytes32 indexed messageId , // The unique ID of the CCIP message.
18
+ uint64 indexed sourceChainSelector , // The chain selector of the source chain.
19
+ address sender , // The address of the sender from the source chain.
20
+ string text , // The text that was received.
21
+ address token , // The token address that was transferred.
22
+ uint256 tokenAmount // The token amount that was transferred.
23
+ );
24
+
25
+ /// @notice The entrypoint for the CCIP router to call. This function should
26
+ /// never revert, all errors should be handled internally in this contract.
27
+ /// @param any2EvmMessage The message to process.
28
+ /// @dev Extremely important to ensure only router calls this.
29
+ function ccipReceive (
30
+ Client.Any2EVMMessage calldata any2EvmMessage
31
+ )
32
+ external
33
+ override
34
+ onlyRouter
35
+ onlyAllowlisted (
36
+ any2EvmMessage.sourceChainSelector,
37
+ abi.decode (any2EvmMessage.sender, (address ))
38
+ ) // Make sure the source chain and sender are allowlisted
39
+ {
40
+ /* solhint-disable no-empty-blocks */
41
+ try this .processMessage (any2EvmMessage) {
42
+ // Intentionally empty in this example; no action needed if processMessage succeeds
43
+ } catch (bytes memory err ) {
44
+ // Could set different error codes based on the caught error. Each could be
45
+ // handled differently.
46
+ s_failedMessages.set (
47
+ any2EvmMessage.messageId,
48
+ uint256 (ErrorCode.BASIC)
49
+ );
50
+ s_messageContents[any2EvmMessage.messageId] = any2EvmMessage;
51
+ // Don't revert so CCIP doesn't revert. Emit event instead.
52
+ // The message can be retried later without having to do manual execution of CCIP.
53
+ emit MessageFailed (any2EvmMessage.messageId, err);
54
+ return ;
55
+ }
56
+ }
57
+
58
+ /// @notice Serves as the entry point for this contract to process incoming messages.
59
+ /// @param any2EvmMessage Received CCIP message.
60
+ /// @dev Transfers specified token amounts to the owner of this contract. This function
61
+ /// must be external because of the try/catch for error handling.
62
+ /// It uses the `onlySelf`: can only be called from the contract.
63
+ function processMessage (
64
+ Client.Any2EVMMessage calldata any2EvmMessage
65
+ )
66
+ external
67
+ onlySelf
68
+ onlyAllowlisted (
69
+ any2EvmMessage.sourceChainSelector,
70
+ abi.decode (any2EvmMessage.sender, (address ))
71
+ ) // Make sure the source chain and sender are allowlisted
72
+ {
73
+ // Simulate a revert for testing purposes
74
+ if (s_simRevert) {
75
+ revert CCIPErrors.ErrorCase ();
76
+ }
77
+ _ccipReceive (any2EvmMessage); // process the message - may revert as well
78
+ }
79
+
80
+ /// handle a received message
81
+ /*function _ccipReceive(
82
+ Client.Any2EVMMessage memory any2EvmMessage
83
+ )
84
+ internal
85
+ override
86
+ onlyAllowlisted(
87
+ any2EvmMessage.sourceChainSelector,
88
+ abi.decode(any2EvmMessage.sender, (address))
89
+ ) // Make sure source chain and sender are allowlisted
90
+ {
91
+ // fetch the messageId
92
+ s_lastReceivedMessageId = any2EvmMessage.messageId;
93
+ // abi-decoding of the sent text
94
+ s_lastReceivedText = abi.decode(any2EvmMessage.data, (string));
95
+
96
+ emit MessageReceived(
97
+ any2EvmMessage.messageId,
98
+ any2EvmMessage.sourceChainSelector, // fetch the source chain identifier (aka selector)
99
+ abi.decode(any2EvmMessage.sender, (address)), // abi-decoding of the sender address,
100
+ abi.decode(any2EvmMessage.data, (string))
101
+ );
102
+ }*/
103
+
104
+ function _ccipReceive (
105
+ Client.Any2EVMMessage memory any2EvmMessage
106
+ ) internal override {
107
+ s_lastReceivedMessageId = any2EvmMessage.messageId; // fetch the messageId
108
+ s_lastReceivedText = abi.decode (any2EvmMessage.data, (string )); // abi-decoding of the sent text
109
+ // Expect one token to be transferred at once, but you can transfer several tokens.
110
+ s_lastReceivedTokenAddress = any2EvmMessage.destTokenAmounts[0 ].token;
111
+ s_lastReceivedTokenAmount = any2EvmMessage.destTokenAmounts[0 ].amount;
112
+ emit MessageReceived (
113
+ any2EvmMessage.messageId,
114
+ any2EvmMessage.sourceChainSelector, // fetch the source chain identifier (aka selector)
115
+ abi.decode (any2EvmMessage.sender, (address )), // abi-decoding of the sender address,
116
+ abi.decode (any2EvmMessage.data, (string )),
117
+ any2EvmMessage.destTokenAmounts[0 ].token,
118
+ any2EvmMessage.destTokenAmounts[0 ].amount
119
+ );
120
+ }
121
+
122
+ function supportsInterface (bytes4 interfaceId ) public virtual pure override ( AuthorizationModule, CCIPReceiverDefensive)
123
+ returns (bool ){
124
+ return ( CCIPReceiverDefensive.supportsInterface (interfaceId) || AuthorizationModule.supportsInterface (interfaceId));
125
+
126
+ }
127
+ }
0 commit comments