@layerzerolabs/protocol-v2-oapp-evm-contracts 1.2.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +15 -0
  2. package/contracts/oapp/OApp.sol +39 -0
  3. package/contracts/oapp/OAppCore.sol +83 -0
  4. package/contracts/oapp/OAppRead.sol +18 -0
  5. package/contracts/oapp/OAppReceiver.sol +122 -0
  6. package/contracts/oapp/OAppSender.sol +124 -0
  7. package/contracts/oapp/examples/CmdCodecV1Mock.sol +31 -0
  8. package/contracts/oapp/examples/LzReadCounter.sol +160 -0
  9. package/contracts/oapp/examples/OmniCounter.sol +15 -0
  10. package/contracts/oapp/examples/OmniCounterAbstract.sol +285 -0
  11. package/contracts/oapp/examples/OmniCounterAlt.sol +90 -0
  12. package/contracts/oapp/examples/OmniCounterPreCrime.sol +102 -0
  13. package/contracts/oapp/interfaces/IOAppComposer.sol +12 -0
  14. package/contracts/oapp/interfaces/IOAppComputer.sol +8 -0
  15. package/contracts/oapp/interfaces/IOAppComputerMap.sol +7 -0
  16. package/contracts/oapp/interfaces/IOAppComputerReduce.sol +7 -0
  17. package/contracts/oapp/interfaces/IOAppCore.sol +52 -0
  18. package/contracts/oapp/interfaces/IOAppMsgInspector.sol +22 -0
  19. package/contracts/oapp/interfaces/IOAppOptionsType3.sol +43 -0
  20. package/contracts/oapp/interfaces/IOAppReceiver.sol +25 -0
  21. package/contracts/oapp/libs/OAppOptionsType3.sol +98 -0
  22. package/contracts/oapp/libs/OptionsBuilder.sol +218 -0
  23. package/contracts/oapp/libs/ReadCmdCodecV1.sol +231 -0
  24. package/contracts/oapp/utils/RateLimiter.sol +229 -0
  25. package/contracts/oft/OFT.sol +89 -0
  26. package/contracts/oft/OFTAdapter.sol +106 -0
  27. package/contracts/oft/OFTCore.sol +399 -0
  28. package/contracts/oft/OFTPrecrime.sol +99 -0
  29. package/contracts/oft/interfaces/IOFT.sol +149 -0
  30. package/contracts/oft/libs/OFTComposeMsgCodec.sol +91 -0
  31. package/contracts/oft/libs/OFTMsgCodec.sol +83 -0
  32. package/contracts/precrime/OAppPreCrimeSimulator.sol +125 -0
  33. package/contracts/precrime/PreCrime.sol +211 -0
  34. package/contracts/precrime/extensions/PreCrimeE1.sol +30 -0
  35. package/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol +55 -0
  36. package/contracts/precrime/interfaces/IPreCrime.sol +40 -0
  37. package/contracts/precrime/libs/Packet.sol +61 -0
  38. package/dist/index.d.ts +7 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +6 -0
  41. package/dist/index.js.map +1 -0
  42. package/package.json +67 -0
@@ -0,0 +1,91 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ library OFTComposeMsgCodec {
6
+ // Offset constants for decoding composed messages
7
+ uint8 private constant NONCE_OFFSET = 8;
8
+ uint8 private constant SRC_EID_OFFSET = 12;
9
+ uint8 private constant AMOUNT_LD_OFFSET = 44;
10
+ uint8 private constant COMPOSE_FROM_OFFSET = 76;
11
+
12
+ /**
13
+ * @dev Encodes a OFT composed message.
14
+ * @param _nonce The nonce value.
15
+ * @param _srcEid The source endpoint ID.
16
+ * @param _amountLD The amount in local decimals.
17
+ * @param _composeMsg The composed message.
18
+ * @return _msg The encoded Composed message.
19
+ */
20
+ function encode(
21
+ uint64 _nonce,
22
+ uint32 _srcEid,
23
+ uint256 _amountLD,
24
+ bytes memory _composeMsg // 0x[composeFrom][composeMsg]
25
+ ) internal pure returns (bytes memory _msg) {
26
+ _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
27
+ }
28
+
29
+ /**
30
+ * @dev Retrieves the nonce from the composed message.
31
+ * @param _msg The message.
32
+ * @return The nonce value.
33
+ */
34
+ function nonce(bytes calldata _msg) internal pure returns (uint64) {
35
+ return uint64(bytes8(_msg[:NONCE_OFFSET]));
36
+ }
37
+
38
+ /**
39
+ * @dev Retrieves the source endpoint ID from the composed message.
40
+ * @param _msg The message.
41
+ * @return The source endpoint ID.
42
+ */
43
+ function srcEid(bytes calldata _msg) internal pure returns (uint32) {
44
+ return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
45
+ }
46
+
47
+ /**
48
+ * @dev Retrieves the amount in local decimals from the composed message.
49
+ * @param _msg The message.
50
+ * @return The amount in local decimals.
51
+ */
52
+ function amountLD(bytes calldata _msg) internal pure returns (uint256) {
53
+ return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
54
+ }
55
+
56
+ /**
57
+ * @dev Retrieves the composeFrom value from the composed message.
58
+ * @param _msg The message.
59
+ * @return The composeFrom value.
60
+ */
61
+ function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
62
+ return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
63
+ }
64
+
65
+ /**
66
+ * @dev Retrieves the composed message.
67
+ * @param _msg The message.
68
+ * @return The composed message.
69
+ */
70
+ function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
71
+ return _msg[COMPOSE_FROM_OFFSET:];
72
+ }
73
+
74
+ /**
75
+ * @dev Converts an address to bytes32.
76
+ * @param _addr The address to convert.
77
+ * @return The bytes32 representation of the address.
78
+ */
79
+ function addressToBytes32(address _addr) internal pure returns (bytes32) {
80
+ return bytes32(uint256(uint160(_addr)));
81
+ }
82
+
83
+ /**
84
+ * @dev Converts bytes32 to an address.
85
+ * @param _b The bytes32 value to convert.
86
+ * @return The address representation of bytes32.
87
+ */
88
+ function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
89
+ return address(uint160(uint256(_b)));
90
+ }
91
+ }
@@ -0,0 +1,83 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ library OFTMsgCodec {
6
+ // Offset constants for encoding and decoding OFT messages
7
+ uint8 private constant SEND_TO_OFFSET = 32;
8
+ uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;
9
+
10
+ /**
11
+ * @dev Encodes an OFT LayerZero message.
12
+ * @param _sendTo The recipient address.
13
+ * @param _amountShared The amount in shared decimals.
14
+ * @param _composeMsg The composed message.
15
+ * @return _msg The encoded message.
16
+ * @return hasCompose A boolean indicating whether the message has a composed payload.
17
+ */
18
+ function encode(
19
+ bytes32 _sendTo,
20
+ uint64 _amountShared,
21
+ bytes memory _composeMsg
22
+ ) internal view returns (bytes memory _msg, bool hasCompose) {
23
+ hasCompose = _composeMsg.length > 0;
24
+ // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.
25
+ _msg = hasCompose
26
+ ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)
27
+ : abi.encodePacked(_sendTo, _amountShared);
28
+ }
29
+
30
+ /**
31
+ * @dev Checks if the OFT message is composed.
32
+ * @param _msg The OFT message.
33
+ * @return A boolean indicating whether the message is composed.
34
+ */
35
+ function isComposed(bytes calldata _msg) internal pure returns (bool) {
36
+ return _msg.length > SEND_AMOUNT_SD_OFFSET;
37
+ }
38
+
39
+ /**
40
+ * @dev Retrieves the recipient address from the OFT message.
41
+ * @param _msg The OFT message.
42
+ * @return The recipient address.
43
+ */
44
+ function sendTo(bytes calldata _msg) internal pure returns (bytes32) {
45
+ return bytes32(_msg[:SEND_TO_OFFSET]);
46
+ }
47
+
48
+ /**
49
+ * @dev Retrieves the amount in shared decimals from the OFT message.
50
+ * @param _msg The OFT message.
51
+ * @return The amount in shared decimals.
52
+ */
53
+ function amountSD(bytes calldata _msg) internal pure returns (uint64) {
54
+ return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));
55
+ }
56
+
57
+ /**
58
+ * @dev Retrieves the composed message from the OFT message.
59
+ * @param _msg The OFT message.
60
+ * @return The composed message.
61
+ */
62
+ function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
63
+ return _msg[SEND_AMOUNT_SD_OFFSET:];
64
+ }
65
+
66
+ /**
67
+ * @dev Converts an address to bytes32.
68
+ * @param _addr The address to convert.
69
+ * @return The bytes32 representation of the address.
70
+ */
71
+ function addressToBytes32(address _addr) internal pure returns (bytes32) {
72
+ return bytes32(uint256(uint160(_addr)));
73
+ }
74
+
75
+ /**
76
+ * @dev Converts bytes32 to an address.
77
+ * @param _b The bytes32 value to convert.
78
+ * @return The address representation of bytes32.
79
+ */
80
+ function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
81
+ return address(uint160(uint256(_b)));
82
+ }
83
+ }
@@ -0,0 +1,125 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
6
+ import { IPreCrime } from "./interfaces/IPreCrime.sol";
7
+ import { IOAppPreCrimeSimulator, InboundPacket, Origin } from "./interfaces/IOAppPreCrimeSimulator.sol";
8
+
9
+ /**
10
+ * @title OAppPreCrimeSimulator
11
+ * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.
12
+ */
13
+ abstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {
14
+ // The address of the preCrime implementation.
15
+ address public preCrime;
16
+
17
+ /**
18
+ * @dev Retrieves the address of the OApp contract.
19
+ * @return The address of the OApp contract.
20
+ *
21
+ * @dev The simulator contract is the base contract for the OApp by default.
22
+ * @dev If the simulator is a separate contract, override this function.
23
+ */
24
+ function oApp() external view virtual returns (address) {
25
+ return address(this);
26
+ }
27
+
28
+ /**
29
+ * @dev Sets the preCrime contract address.
30
+ * @param _preCrime The address of the preCrime contract.
31
+ */
32
+ function setPreCrime(address _preCrime) public virtual onlyOwner {
33
+ preCrime = _preCrime;
34
+ emit PreCrimeSet(_preCrime);
35
+ }
36
+
37
+ /**
38
+ * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.
39
+ * @param _packets An array of InboundPacket objects representing received packets to be delivered.
40
+ *
41
+ * @dev WARNING: MUST revert at the end with the simulation results.
42
+ * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,
43
+ * WITHOUT actually executing them.
44
+ */
45
+ function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {
46
+ for (uint256 i = 0; i < _packets.length; i++) {
47
+ InboundPacket calldata packet = _packets[i];
48
+
49
+ // Ignore packets that are not from trusted peers.
50
+ if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;
51
+
52
+ // @dev Because a verifier is calling this function, it doesnt have access to executor params:
53
+ // - address _executor
54
+ // - bytes calldata _extraData
55
+ // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().
56
+ // They are instead stubbed to default values, address(0) and bytes("")
57
+ // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,
58
+ // which would cause the revert to be ignored.
59
+ this.lzReceiveSimulate{ value: packet.value }(
60
+ packet.origin,
61
+ packet.guid,
62
+ packet.message,
63
+ packet.executor,
64
+ packet.extraData
65
+ );
66
+ }
67
+
68
+ // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().
69
+ revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());
70
+ }
71
+
72
+ /**
73
+ * @dev Is effectively an internal function because msg.sender must be address(this).
74
+ * Allows resetting the call stack for 'internal' calls.
75
+ * @param _origin The origin information containing the source endpoint and sender address.
76
+ * - srcEid: The source chain endpoint ID.
77
+ * - sender: The sender address on the src chain.
78
+ * - nonce: The nonce of the message.
79
+ * @param _guid The unique identifier of the packet.
80
+ * @param _message The message payload of the packet.
81
+ * @param _executor The executor address for the packet.
82
+ * @param _extraData Additional data for the packet.
83
+ */
84
+ function lzReceiveSimulate(
85
+ Origin calldata _origin,
86
+ bytes32 _guid,
87
+ bytes calldata _message,
88
+ address _executor,
89
+ bytes calldata _extraData
90
+ ) external payable virtual {
91
+ // @dev Ensure ONLY can be called 'internally'.
92
+ if (msg.sender != address(this)) revert OnlySelf();
93
+ _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);
94
+ }
95
+
96
+ /**
97
+ * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.
98
+ * @param _origin The origin information.
99
+ * - srcEid: The source chain endpoint ID.
100
+ * - sender: The sender address from the src chain.
101
+ * - nonce: The nonce of the LayerZero message.
102
+ * @param _guid The GUID of the LayerZero message.
103
+ * @param _message The LayerZero message.
104
+ * @param _executor The address of the off-chain executor.
105
+ * @param _extraData Arbitrary data passed by the msg executor.
106
+ *
107
+ * @dev Enables the preCrime simulator to mock sending lzReceive() messages,
108
+ * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.
109
+ */
110
+ function _lzReceiveSimulate(
111
+ Origin calldata _origin,
112
+ bytes32 _guid,
113
+ bytes calldata _message,
114
+ address _executor,
115
+ bytes calldata _extraData
116
+ ) internal virtual;
117
+
118
+ /**
119
+ * @dev checks if the specified peer is considered 'trusted' by the OApp.
120
+ * @param _eid The endpoint Id to check.
121
+ * @param _peer The peer to check.
122
+ * @return Whether the peer passed is considered 'trusted' by the OApp.
123
+ */
124
+ function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);
125
+ }
@@ -0,0 +1,211 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
6
+ import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol";
7
+ import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol";
8
+
9
+ import { IPreCrime, PreCrimePeer } from "./interfaces/IPreCrime.sol";
10
+ import { IOAppPreCrimeSimulator } from "./interfaces/IOAppPreCrimeSimulator.sol";
11
+ import { InboundPacket, PacketDecoder } from "./libs/Packet.sol";
12
+
13
+ abstract contract PreCrime is Ownable, IPreCrime {
14
+ using BytesLib for bytes;
15
+
16
+ uint16 internal constant CONFIG_VERSION = 2;
17
+ address internal constant OFF_CHAIN_CALLER = address(0xDEAD);
18
+
19
+ address internal immutable lzEndpoint;
20
+ address public immutable simulator;
21
+ address public immutable oApp;
22
+
23
+ // preCrime config
24
+ uint64 public maxBatchSize;
25
+ PreCrimePeer[] internal preCrimePeers;
26
+
27
+ /// @dev getConfig(), simulate() and preCrime() are not view functions because it is more flexible to be able to
28
+ /// update state for some complex logic. So onlyOffChain() modifier is to make sure they are only called
29
+ /// by the off-chain.
30
+ modifier onlyOffChain() {
31
+ if (msg.sender != OFF_CHAIN_CALLER) revert OnlyOffChain();
32
+ _;
33
+ }
34
+
35
+ constructor(address _endpoint, address _simulator) {
36
+ lzEndpoint = _endpoint;
37
+ simulator = _simulator;
38
+ oApp = IOAppPreCrimeSimulator(_simulator).oApp();
39
+ }
40
+
41
+ function setMaxBatchSize(uint64 _maxBatchSize) external onlyOwner {
42
+ maxBatchSize = _maxBatchSize;
43
+ }
44
+
45
+ function setPreCrimePeers(PreCrimePeer[] calldata _preCrimePeers) external onlyOwner {
46
+ delete preCrimePeers;
47
+ for (uint256 i = 0; i < _preCrimePeers.length; ++i) {
48
+ preCrimePeers.push(_preCrimePeers[i]);
49
+ }
50
+ }
51
+
52
+ function getPreCrimePeers() external view returns (PreCrimePeer[] memory) {
53
+ return preCrimePeers;
54
+ }
55
+
56
+ function getConfig(
57
+ bytes[] calldata _packets,
58
+ uint256[] calldata _packetMsgValues
59
+ ) external onlyOffChain returns (bytes memory) {
60
+ bytes memory config = abi.encodePacked(CONFIG_VERSION, maxBatchSize);
61
+
62
+ // if no packets, return config with all peers
63
+ PreCrimePeer[] memory peers = _packets.length == 0
64
+ ? preCrimePeers
65
+ : _getPreCrimePeers(PacketDecoder.decode(_packets, _packetMsgValues));
66
+
67
+ if (peers.length > 0) {
68
+ uint16 size = uint16(peers.length);
69
+ config = abi.encodePacked(config, size);
70
+
71
+ for (uint256 i = 0; i < size; ++i) {
72
+ config = abi.encodePacked(config, peers[i].eid, peers[i].preCrime, peers[i].oApp);
73
+ }
74
+ }
75
+
76
+ return config;
77
+ }
78
+
79
+ // @dev _packetMsgValues refers to the 'lzReceive' option passed per packet
80
+ function simulate(
81
+ bytes[] calldata _packets,
82
+ uint256[] calldata _packetMsgValues
83
+ ) external payable override onlyOffChain returns (bytes memory) {
84
+ InboundPacket[] memory packets = PacketDecoder.decode(_packets, _packetMsgValues);
85
+ _checkPacketSizeAndOrder(packets);
86
+ return _simulate(packets);
87
+ }
88
+
89
+ function preCrime(
90
+ bytes[] calldata _packets,
91
+ uint256[] calldata _packetMsgValues,
92
+ bytes[] calldata _simulations
93
+ ) external onlyOffChain {
94
+ InboundPacket[] memory packets = PacketDecoder.decode(_packets, _packetMsgValues);
95
+ uint32[] memory eids = new uint32[](_simulations.length);
96
+ bytes[] memory simulations = new bytes[](_simulations.length);
97
+
98
+ for (uint256 i = 0; i < _simulations.length; ++i) {
99
+ bytes calldata simulation = _simulations[i];
100
+ eids[i] = uint32(bytes4(simulation[0:4]));
101
+ simulations[i] = simulation[4:];
102
+ }
103
+ _checkResultsCompleteness(packets, eids);
104
+
105
+ _preCrime(packets, eids, simulations);
106
+ }
107
+
108
+ function version() external pure returns (uint64 major, uint8 minor) {
109
+ return (2, 0);
110
+ }
111
+
112
+ function _checkResultsCompleteness(InboundPacket[] memory _packets, uint32[] memory _eids) internal {
113
+ // check if all peers result included
114
+ if (_packets.length > 0) {
115
+ PreCrimePeer[] memory peers = _getPreCrimePeers(_packets);
116
+ for (uint256 i = 0; i < peers.length; i++) {
117
+ uint32 expectedEid = peers[i].eid;
118
+ if (!_isContain(_eids, expectedEid)) revert SimulationResultNotFound(expectedEid);
119
+ }
120
+ }
121
+
122
+ // check if local result included
123
+ uint32 localEid = _getLocalEid();
124
+ if (!_isContain(_eids, localEid)) revert SimulationResultNotFound(localEid);
125
+ }
126
+
127
+ function _isContain(uint32[] memory _array, uint32 _item) internal pure returns (bool) {
128
+ for (uint256 i = 0; i < _array.length; i++) {
129
+ if (_array[i] == _item) return true;
130
+ }
131
+ return false;
132
+ }
133
+
134
+ function _checkPacketSizeAndOrder(InboundPacket[] memory _packets) internal view {
135
+ if (_packets.length > maxBatchSize) revert PacketOversize(maxBatchSize, _packets.length);
136
+
137
+ // check packets nonce, sequence order
138
+ // packets should ordered in ascending order by srcEid, sender, nonce
139
+ if (_packets.length > 0) {
140
+ uint32 srcEid;
141
+ bytes32 sender;
142
+ uint64 nonce;
143
+ for (uint256 i = 0; i < _packets.length; i++) {
144
+ InboundPacket memory packet = _packets[i];
145
+
146
+ // skip if not from trusted peer
147
+ if (!IOAppPreCrimeSimulator(simulator).isPeer(packet.origin.srcEid, packet.origin.sender)) continue;
148
+
149
+ if (
150
+ packet.origin.srcEid < srcEid || (packet.origin.srcEid == srcEid && packet.origin.sender < sender)
151
+ ) {
152
+ revert PacketUnsorted();
153
+ } else if (packet.origin.srcEid != srcEid || packet.origin.sender != sender) {
154
+ // start from a new chain or a new source oApp
155
+ srcEid = packet.origin.srcEid;
156
+ sender = packet.origin.sender;
157
+ nonce = _getInboundNonce(srcEid, sender);
158
+ }
159
+ // TODO ??
160
+ // Wont the nonce order not matter and enforced at the OApp level? the simulation will revert?
161
+
162
+ // the following packet's nonce add 1 in order
163
+ if (packet.origin.nonce != ++nonce) revert PacketUnsorted();
164
+ }
165
+ }
166
+ }
167
+
168
+ function _simulate(InboundPacket[] memory _packets) internal virtual returns (bytes memory) {
169
+ (bool success, bytes memory returnData) = simulator.call{ value: msg.value }(
170
+ abi.encodeWithSelector(IOAppPreCrimeSimulator.lzReceiveAndRevert.selector, _packets)
171
+ );
172
+
173
+ bytes memory result = _parseRevertResult(success, returnData);
174
+ return abi.encodePacked(_getLocalEid(), result); // add localEid at the first of the result
175
+ }
176
+
177
+ function _parseRevertResult(bool _success, bytes memory _returnData) internal pure returns (bytes memory result) {
178
+ // should always revert with LzReceiveRevert
179
+ if (_success) revert SimulationFailed("no revert");
180
+
181
+ // if not expected selector, bubble up error
182
+ if (bytes4(_returnData) != IOAppPreCrimeSimulator.SimulationResult.selector) {
183
+ revert SimulationFailed(_returnData);
184
+ }
185
+
186
+ // Slice the sighash. Remove the selector which is the first 4 bytes
187
+ result = _returnData.slice(4, _returnData.length - 4);
188
+ result = abi.decode(result, (bytes));
189
+ }
190
+
191
+ // to be compatible with EndpointV1
192
+ function _getLocalEid() internal view virtual returns (uint32) {
193
+ return ILayerZeroEndpointV2(lzEndpoint).eid();
194
+ }
195
+
196
+ // to be compatible with EndpointV1
197
+ function _getInboundNonce(uint32 _srcEid, bytes32 _sender) internal view virtual returns (uint64) {
198
+ return ILayerZeroEndpointV2(lzEndpoint).inboundNonce(oApp, _srcEid, _sender);
199
+ }
200
+
201
+ // ----------------- to be implemented -----------------
202
+ function buildSimulationResult() external view virtual override returns (bytes memory);
203
+
204
+ function _getPreCrimePeers(InboundPacket[] memory _packets) internal virtual returns (PreCrimePeer[] memory peers);
205
+
206
+ function _preCrime(
207
+ InboundPacket[] memory _packets,
208
+ uint32[] memory _eids,
209
+ bytes[] memory _simulations
210
+ ) internal virtual;
211
+ }
@@ -0,0 +1,30 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
6
+
7
+ import { ILayerZeroEndpoint } from "@layerzerolabs/lz-evm-v1-0.7/contracts/interfaces/ILayerZeroEndpoint.sol";
8
+
9
+ import { PreCrime } from "../PreCrime.sol";
10
+
11
+ abstract contract PreCrimeE1 is PreCrime {
12
+ using SafeCast for uint32;
13
+
14
+ uint32 internal immutable localEid;
15
+
16
+ constructor(uint32 _localEid, address _endpoint, address _simulator) PreCrime(_endpoint, _simulator) {
17
+ localEid = _localEid;
18
+ }
19
+
20
+ function _getLocalEid() internal view override returns (uint32) {
21
+ return localEid;
22
+ }
23
+
24
+ function _getInboundNonce(uint32 _srcEid, bytes32 _sender) internal view override returns (uint64) {
25
+ bytes memory path = _getPath(_srcEid, _sender);
26
+ return ILayerZeroEndpoint(lzEndpoint).getInboundNonce(_srcEid.toUint16(), path);
27
+ }
28
+
29
+ function _getPath(uint32 _srcEid, bytes32 _sender) internal view virtual returns (bytes memory);
30
+ }
@@ -0,0 +1,55 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ // @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.
6
+ // solhint-disable-next-line no-unused-import
7
+ import { InboundPacket, Origin } from "../libs/Packet.sol";
8
+
9
+ /**
10
+ * @title IOAppPreCrimeSimulator Interface
11
+ * @dev Interface for the preCrime simulation functionality in an OApp.
12
+ */
13
+ interface IOAppPreCrimeSimulator {
14
+ // @dev simulation result used in PreCrime implementation
15
+ error SimulationResult(bytes result);
16
+ error OnlySelf();
17
+
18
+ /**
19
+ * @dev Emitted when the preCrime contract address is set.
20
+ * @param preCrimeAddress The address of the preCrime contract.
21
+ */
22
+ event PreCrimeSet(address preCrimeAddress);
23
+
24
+ /**
25
+ * @dev Retrieves the address of the preCrime contract implementation.
26
+ * @return The address of the preCrime contract.
27
+ */
28
+ function preCrime() external view returns (address);
29
+
30
+ /**
31
+ * @dev Retrieves the address of the OApp contract.
32
+ * @return The address of the OApp contract.
33
+ */
34
+ function oApp() external view returns (address);
35
+
36
+ /**
37
+ * @dev Sets the preCrime contract address.
38
+ * @param _preCrime The address of the preCrime contract.
39
+ */
40
+ function setPreCrime(address _preCrime) external;
41
+
42
+ /**
43
+ * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.
44
+ * @param _packets An array of LayerZero InboundPacket objects representing received packets.
45
+ */
46
+ function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;
47
+
48
+ /**
49
+ * @dev checks if the specified peer is considered 'trusted' by the OApp.
50
+ * @param _eid The endpoint Id to check.
51
+ * @param _peer The peer to check.
52
+ * @return Whether the peer passed is considered 'trusted' by the OApp.
53
+ */
54
+ function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);
55
+ }
@@ -0,0 +1,40 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+ struct PreCrimePeer {
5
+ uint32 eid;
6
+ bytes32 preCrime;
7
+ bytes32 oApp;
8
+ }
9
+
10
+ // TODO not done yet
11
+ interface IPreCrime {
12
+ error OnlyOffChain();
13
+
14
+ // for simulate()
15
+ error PacketOversize(uint256 max, uint256 actual);
16
+ error PacketUnsorted();
17
+ error SimulationFailed(bytes reason);
18
+
19
+ // for preCrime()
20
+ error SimulationResultNotFound(uint32 eid);
21
+ error InvalidSimulationResult(uint32 eid, bytes reason);
22
+ error CrimeFound(bytes crime);
23
+
24
+ function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);
25
+
26
+ function simulate(
27
+ bytes[] calldata _packets,
28
+ uint256[] calldata _packetMsgValues
29
+ ) external payable returns (bytes memory);
30
+
31
+ function buildSimulationResult() external view returns (bytes memory);
32
+
33
+ function preCrime(
34
+ bytes[] calldata _packets,
35
+ uint256[] calldata _packetMsgValues,
36
+ bytes[] calldata _simulations
37
+ ) external;
38
+
39
+ function version() external view returns (uint64 major, uint8 minor);
40
+ }