@layerzerolabs/protocol-stellar-v2 0.2.8

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 (265) hide show
  1. package/.turbo/turbo-build.log +727 -0
  2. package/.turbo/turbo-lint.log +158 -0
  3. package/.turbo/turbo-test.log +796 -0
  4. package/Cargo.lock +2237 -0
  5. package/Cargo.toml +63 -0
  6. package/clippy.toml +7 -0
  7. package/contracts/common-macros/Cargo.toml +20 -0
  8. package/contracts/common-macros/src/error.rs +53 -0
  9. package/contracts/common-macros/src/event.rs +16 -0
  10. package/contracts/common-macros/src/lib.rs +255 -0
  11. package/contracts/common-macros/src/ownable.rs +63 -0
  12. package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +310 -0
  13. package/contracts/common-macros/src/storage.rs +439 -0
  14. package/contracts/common-macros/src/tests.rs +287 -0
  15. package/contracts/common-macros/src/ttl_configurable.rs +60 -0
  16. package/contracts/endpoint-v2/ARCHITECTURE.md +233 -0
  17. package/contracts/endpoint-v2/Cargo.toml +30 -0
  18. package/contracts/endpoint-v2/src/constants.rs +52 -0
  19. package/contracts/endpoint-v2/src/endpoint_v2.rs +305 -0
  20. package/contracts/endpoint-v2/src/errors.rs +29 -0
  21. package/contracts/endpoint-v2/src/events.rs +207 -0
  22. package/contracts/endpoint-v2/src/interfaces/layerzero_composer.rs +26 -0
  23. package/contracts/endpoint-v2/src/interfaces/layerzero_endpoint_v2.rs +170 -0
  24. package/contracts/endpoint-v2/src/interfaces/layerzero_receiver.rs +43 -0
  25. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +62 -0
  26. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +220 -0
  27. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +121 -0
  28. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +63 -0
  29. package/contracts/endpoint-v2/src/interfaces/mod.rs +17 -0
  30. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +70 -0
  31. package/contracts/endpoint-v2/src/lib.rs +22 -0
  32. package/contracts/endpoint-v2/src/message_lib_manager.rs +315 -0
  33. package/contracts/endpoint-v2/src/messaging_channel.rs +218 -0
  34. package/contracts/endpoint-v2/src/messaging_composer.rs +76 -0
  35. package/contracts/endpoint-v2/src/storage.rs +78 -0
  36. package/contracts/endpoint-v2/src/tests/endpoint_setup.rs +131 -0
  37. package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +237 -0
  38. package/contracts/endpoint-v2/src/tests/endpoint_v2/delegate.rs +42 -0
  39. package/contracts/endpoint-v2/src/tests/endpoint_v2/initializable.rs +76 -0
  40. package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +211 -0
  41. package/contracts/endpoint-v2/src/tests/endpoint_v2/mod.rs +18 -0
  42. package/contracts/endpoint-v2/src/tests/endpoint_v2/native_token.rs +10 -0
  43. package/contracts/endpoint-v2/src/tests/endpoint_v2/owner.rs +10 -0
  44. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +424 -0
  45. package/contracts/endpoint-v2/src/tests/endpoint_v2/quote.rs +144 -0
  46. package/contracts/endpoint-v2/src/tests/endpoint_v2/recover_token.rs +72 -0
  47. package/contracts/endpoint-v2/src/tests/endpoint_v2/require_oapp_auth.rs +29 -0
  48. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +513 -0
  49. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +43 -0
  50. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +27 -0
  51. package/contracts/endpoint-v2/src/tests/endpoint_v2/transfer_ownership.rs +30 -0
  52. package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +202 -0
  53. package/contracts/endpoint-v2/src/tests/endpoint_v2/verifiable.rs +59 -0
  54. package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +172 -0
  55. package/contracts/endpoint-v2/src/tests/endpoint_v2/zro.rs +23 -0
  56. package/contracts/endpoint-v2/src/tests/message_lib_manager/mod.rs +10 -0
  57. package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +131 -0
  58. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_registered.rs +35 -0
  59. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_supported_eid.rs +28 -0
  60. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_config.rs +79 -0
  61. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +246 -0
  62. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +285 -0
  63. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +180 -0
  64. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +405 -0
  65. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +80 -0
  66. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +131 -0
  67. package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +358 -0
  68. package/contracts/endpoint-v2/src/tests/messaging_channel/clear.rs +316 -0
  69. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound_nonce.rs +288 -0
  70. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound_payload_hash.rs +316 -0
  71. package/contracts/endpoint-v2/src/tests/messaging_channel/internal.rs +388 -0
  72. package/contracts/endpoint-v2/src/tests/messaging_channel/lazy_inbound_nonce.rs +307 -0
  73. package/contracts/endpoint-v2/src/tests/messaging_channel/mod.rs +10 -0
  74. package/contracts/endpoint-v2/src/tests/messaging_channel/next_guid.rs +239 -0
  75. package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +324 -0
  76. package/contracts/endpoint-v2/src/tests/messaging_channel/outbound_nonce.rs +242 -0
  77. package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +232 -0
  78. package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +212 -0
  79. package/contracts/endpoint-v2/src/tests/messaging_composer/compose_queue.rs +213 -0
  80. package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +269 -0
  81. package/contracts/endpoint-v2/src/tests/messaging_composer/mod.rs +4 -0
  82. package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +173 -0
  83. package/contracts/endpoint-v2/src/tests/mock.rs +132 -0
  84. package/contracts/endpoint-v2/src/tests/mod.rs +12 -0
  85. package/contracts/endpoint-v2/src/tests/util/build_payload.rs +126 -0
  86. package/contracts/endpoint-v2/src/tests/util/compute_guid.rs +82 -0
  87. package/contracts/endpoint-v2/src/tests/util/keccak256.rs +115 -0
  88. package/contracts/endpoint-v2/src/tests/util/mod.rs +3 -0
  89. package/contracts/endpoint-v2/src/util.rs +52 -0
  90. package/contracts/message-libs/Cargo.toml +12 -0
  91. package/contracts/message-libs/block-message-lib/Cargo.toml +19 -0
  92. package/contracts/message-libs/block-message-lib/src/lib.rs +70 -0
  93. package/contracts/message-libs/lib.rs +2 -0
  94. package/contracts/message-libs/message-lib-common/Cargo.toml +24 -0
  95. package/contracts/message-libs/message-lib-common/src/errors.rs +20 -0
  96. package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +55 -0
  97. package/contracts/message-libs/message-lib-common/src/interfaces/executor.rs +46 -0
  98. package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +7 -0
  99. package/contracts/message-libs/message-lib-common/src/interfaces/treasury.rs +17 -0
  100. package/contracts/message-libs/message-lib-common/src/lib.rs +14 -0
  101. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +99 -0
  102. package/contracts/message-libs/message-lib-common/src/testing_utils.rs +27 -0
  103. package/contracts/message-libs/message-lib-common/src/tests/mod.rs +2 -0
  104. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +162 -0
  105. package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +319 -0
  106. package/contracts/message-libs/message-lib-common/src/worker_options.rs +190 -0
  107. package/contracts/message-libs/simple-message-lib/Cargo.toml +26 -0
  108. package/contracts/message-libs/simple-message-lib/src/errors.rs +11 -0
  109. package/contracts/message-libs/simple-message-lib/src/lib.rs +14 -0
  110. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +136 -0
  111. package/contracts/message-libs/simple-message-lib/src/storage.rs +27 -0
  112. package/contracts/message-libs/simple-message-lib/src/test.rs +280 -0
  113. package/contracts/message-libs/treasury/Cargo.toml +27 -0
  114. package/contracts/message-libs/treasury/src/errors.rs +10 -0
  115. package/contracts/message-libs/treasury/src/events.rs +28 -0
  116. package/contracts/message-libs/treasury/src/interfaces/mod.rs +3 -0
  117. package/contracts/message-libs/treasury/src/interfaces/zro_fee_lib.rs +20 -0
  118. package/contracts/message-libs/treasury/src/lib.rs +20 -0
  119. package/contracts/message-libs/treasury/src/storage.rs +18 -0
  120. package/contracts/message-libs/treasury/src/tests/mod.rs +2 -0
  121. package/contracts/message-libs/treasury/src/tests/setup.rs +112 -0
  122. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +562 -0
  123. package/contracts/message-libs/treasury/src/treasury.rs +140 -0
  124. package/contracts/message-libs/uln-302/Cargo.toml +28 -0
  125. package/contracts/message-libs/uln-302/src/config_validation.rs +173 -0
  126. package/contracts/message-libs/uln-302/src/errors.rs +29 -0
  127. package/contracts/message-libs/uln-302/src/events.rs +72 -0
  128. package/contracts/message-libs/uln-302/src/interfaces/mod.rs +5 -0
  129. package/contracts/message-libs/uln-302/src/interfaces/receive.rs +82 -0
  130. package/contracts/message-libs/uln-302/src/interfaces/send.rs +159 -0
  131. package/contracts/message-libs/uln-302/src/lib.rs +20 -0
  132. package/contracts/message-libs/uln-302/src/receive.rs +199 -0
  133. package/contracts/message-libs/uln-302/src/send.rs +349 -0
  134. package/contracts/message-libs/uln-302/src/storage.rs +47 -0
  135. package/contracts/message-libs/uln-302/src/tests/config/mod.rs +2 -0
  136. package/contracts/message-libs/uln-302/src/tests/config/oapp_uln_config.rs +291 -0
  137. package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +163 -0
  138. package/contracts/message-libs/uln-302/src/tests/mod.rs +7 -0
  139. package/contracts/message-libs/uln-302/src/tests/receive_uln302/commit_verification.rs +183 -0
  140. package/contracts/message-libs/uln-302/src/tests/receive_uln302/confirmations.rs +128 -0
  141. package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +104 -0
  142. package/contracts/message-libs/uln-302/src/tests/receive_uln302/mod.rs +66 -0
  143. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +79 -0
  144. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verifiable.rs +463 -0
  145. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +173 -0
  146. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +132 -0
  147. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +117 -0
  148. package/contracts/message-libs/uln-302/src/tests/send_uln302/mod.rs +6 -0
  149. package/contracts/message-libs/uln-302/src/tests/send_uln302/quote.rs +586 -0
  150. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +834 -0
  151. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +95 -0
  152. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +80 -0
  153. package/contracts/message-libs/uln-302/src/tests/setup.rs +268 -0
  154. package/contracts/message-libs/uln-302/src/tests/testing_utils.rs +47 -0
  155. package/contracts/message-libs/uln-302/src/tests/uln302/get_app_receive_uln_config.rs +51 -0
  156. package/contracts/message-libs/uln-302/src/tests/uln302/get_app_send_uln_config.rs +51 -0
  157. package/contracts/message-libs/uln-302/src/tests/uln302/get_oapp_executor_config.rs +48 -0
  158. package/contracts/message-libs/uln-302/src/tests/uln302/mod.rs +4 -0
  159. package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +998 -0
  160. package/contracts/message-libs/uln-302/src/uln302.rs +117 -0
  161. package/contracts/oapp-macros/Cargo.toml +21 -0
  162. package/contracts/oapp-macros/src/lib.rs +408 -0
  163. package/contracts/oapp-macros/src/oapp_core.rs +49 -0
  164. package/contracts/oapp-macros/src/oapp_full.rs +15 -0
  165. package/contracts/oapp-macros/src/oapp_options_type3.rs +46 -0
  166. package/contracts/oapp-macros/src/oapp_receiver.rs +67 -0
  167. package/contracts/oapp-macros/src/oapp_sender.rs +23 -0
  168. package/contracts/oapp-macros/src/util.rs +103 -0
  169. package/contracts/oapp-macros/tests/test_macros.rs +522 -0
  170. package/contracts/oapps/Cargo.toml +12 -0
  171. package/contracts/oapps/counter/Cargo.toml +24 -0
  172. package/contracts/oapps/counter/integration_tests/mod.rs +3 -0
  173. package/contracts/oapps/counter/integration_tests/setup.rs +201 -0
  174. package/contracts/oapps/counter/integration_tests/test_with_sml.rs +166 -0
  175. package/contracts/oapps/counter/integration_tests/utils.rs +144 -0
  176. package/contracts/oapps/counter/src/codec.rs +63 -0
  177. package/contracts/oapps/counter/src/counter.rs +235 -0
  178. package/contracts/oapps/counter/src/errors.rs +9 -0
  179. package/contracts/oapps/counter/src/lib.rs +16 -0
  180. package/contracts/oapps/counter/src/options.rs +30 -0
  181. package/contracts/oapps/counter/src/storage.rs +33 -0
  182. package/contracts/oapps/counter/src/tests/mod.rs +37 -0
  183. package/contracts/oapps/counter/src/tests/test_codec.rs +64 -0
  184. package/contracts/oapps/counter/src/tests/test_counter.rs +390 -0
  185. package/contracts/oapps/counter/src/u256_ext.rs +21 -0
  186. package/contracts/oapps/lib.rs +2 -0
  187. package/contracts/oapps/oapp/Cargo.toml +21 -0
  188. package/contracts/oapps/oapp/src/errors.rs +9 -0
  189. package/contracts/oapps/oapp/src/lib.rs +10 -0
  190. package/contracts/oapps/oapp/src/oapp_core.rs +92 -0
  191. package/contracts/oapps/oapp/src/oapp_options_type3.rs +89 -0
  192. package/contracts/oapps/oapp/src/oapp_receiver.rs +72 -0
  193. package/contracts/oapps/oapp/src/oapp_sender.rs +66 -0
  194. package/contracts/oapps/oapp/src/tests/mod.rs +4 -0
  195. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +162 -0
  196. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +180 -0
  197. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +157 -0
  198. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +283 -0
  199. package/contracts/utils/Cargo.toml +21 -0
  200. package/contracts/utils/src/buffer_reader.rs +143 -0
  201. package/contracts/utils/src/buffer_writer.rs +117 -0
  202. package/contracts/utils/src/bytes_ext.rs +19 -0
  203. package/contracts/utils/src/errors.rs +30 -0
  204. package/contracts/utils/src/lib.rs +15 -0
  205. package/contracts/utils/src/option_ext.rs +38 -0
  206. package/contracts/utils/src/ownable.rs +88 -0
  207. package/contracts/utils/src/testing_utils.rs +100 -0
  208. package/contracts/utils/src/tests/buffer_reader.rs +1006 -0
  209. package/contracts/utils/src/tests/buffer_writer.rs +330 -0
  210. package/contracts/utils/src/tests/bytes_ext.rs +77 -0
  211. package/contracts/utils/src/tests/mod.rs +4 -0
  212. package/contracts/utils/src/tests/ownable.rs +149 -0
  213. package/contracts/utils/src/ttl.rs +164 -0
  214. package/contracts/workers/Cargo.toml +13 -0
  215. package/contracts/workers/executor/Cargo.toml +26 -0
  216. package/contracts/workers/executor/src/events.rs +22 -0
  217. package/contracts/workers/executor/src/executor.rs +347 -0
  218. package/contracts/workers/executor/src/interfaces/executor.rs +40 -0
  219. package/contracts/workers/executor/src/interfaces/mod.rs +5 -0
  220. package/contracts/workers/executor/src/interfaces/types.rs +51 -0
  221. package/contracts/workers/executor/src/lib.rs +10 -0
  222. package/contracts/workers/executor/src/storage.rs +23 -0
  223. package/contracts/workers/lib.rs +2 -0
  224. package/contracts/workers/worker-common/Cargo.toml +18 -0
  225. package/contracts/workers/worker-common/src/constants.rs +17 -0
  226. package/contracts/workers/worker-common/src/errors.rs +6 -0
  227. package/contracts/workers/worker-common/src/events.rs +34 -0
  228. package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +35 -0
  229. package/contracts/workers/worker-common/src/interfaces/mod.rs +7 -0
  230. package/contracts/workers/worker-common/src/interfaces/price_feed.rs +40 -0
  231. package/contracts/workers/worker-common/src/interfaces/worker.rs +60 -0
  232. package/contracts/workers/worker-common/src/lib.rs +19 -0
  233. package/contracts/workers/worker-common/src/storage.rs +32 -0
  234. package/contracts/workers/worker-common/src/worker_common.rs +166 -0
  235. package/package.json +25 -0
  236. package/rust-toolchain.toml +4 -0
  237. package/rustfmt.toml +17 -0
  238. package/sdk/.turbo/turbo-build.log +4 -0
  239. package/sdk/dist/generated/bml.d.ts +452 -0
  240. package/sdk/dist/generated/bml.js +72 -0
  241. package/sdk/dist/generated/counter.d.ts +824 -0
  242. package/sdk/dist/generated/counter.js +125 -0
  243. package/sdk/dist/generated/endpoint.d.ts +1676 -0
  244. package/sdk/dist/generated/endpoint.js +216 -0
  245. package/sdk/dist/generated/sml.d.ts +810 -0
  246. package/sdk/dist/generated/sml.js +132 -0
  247. package/sdk/dist/generated/uln302.d.ts +1227 -0
  248. package/sdk/dist/generated/uln302.js +185 -0
  249. package/sdk/dist/index.d.ts +5 -0
  250. package/sdk/dist/index.js +5 -0
  251. package/sdk/node_modules/.bin/tsc +21 -0
  252. package/sdk/node_modules/.bin/tsserver +21 -0
  253. package/sdk/node_modules/.bin/vitest +21 -0
  254. package/sdk/node_modules/.bin/zx +21 -0
  255. package/sdk/package.json +40 -0
  256. package/sdk/src/index.ts +5 -0
  257. package/sdk/test/index.test.ts +271 -0
  258. package/sdk/test/suites/constants.ts +13 -0
  259. package/sdk/test/suites/deploy.ts +277 -0
  260. package/sdk/test/suites/localnet.ts +42 -0
  261. package/sdk/test/suites/scan.ts +189 -0
  262. package/sdk/tsconfig.json +106 -0
  263. package/tools/ts-bindings-gen/Cargo.toml +14 -0
  264. package/tools/ts-bindings-gen/src/main.rs +147 -0
  265. package/turbo.json +12 -0
@@ -0,0 +1,316 @@
1
+ use soroban_sdk::{testutils::Address as _, Address, Bytes, BytesN, IntoVal};
2
+
3
+ use crate::{
4
+ endpoint_v2::EndpointV2,
5
+ errors::EndpointError,
6
+ events::PacketDelivered,
7
+ interfaces::Origin,
8
+ storage,
9
+ tests::endpoint_setup::setup,
10
+ util::{build_payload, compute_guid},
11
+ };
12
+ use utils::testing_utils::assert_event;
13
+
14
+ #[test]
15
+ fn test_clear_success() {
16
+ let test_setup = setup();
17
+ let env = &test_setup.env;
18
+ let endpoint_client = &test_setup.endpoint_client;
19
+
20
+ let receiver = Address::generate(env);
21
+ let src_eid = 2;
22
+ let sender_bytes = BytesN::from_array(env, &[1u8; 32]);
23
+ let nonce = 1;
24
+ let message = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
25
+
26
+ // Compute guid and build payload
27
+ let guid =
28
+ env.as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
29
+ let payload = env.as_contract(&endpoint_client.address, || build_payload(env, &guid, &message));
30
+
31
+ // Compute and store payload hash
32
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
33
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
34
+ });
35
+ env.as_contract(&endpoint_client.address, || {
36
+ EndpointV2::inbound(env, &receiver, src_eid, &sender_bytes, nonce, &payload_hash)
37
+ });
38
+
39
+ // Verify payload hash is stored
40
+ let stored = env.as_contract(&endpoint_client.address, || {
41
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender_bytes, nonce)
42
+ });
43
+ assert_eq!(stored, Some(payload_hash.clone()));
44
+
45
+ // Clear the payload (receiver authorizes itself)
46
+ let origin = Origin { src_eid, sender: sender_bytes.clone(), nonce };
47
+ endpoint_client
48
+ .mock_auths(&[soroban_sdk::testutils::MockAuth {
49
+ address: &receiver,
50
+ invoke: &soroban_sdk::testutils::MockAuthInvoke {
51
+ contract: &endpoint_client.address,
52
+ fn_name: "clear",
53
+ args: (&receiver, &origin, &receiver, &guid, &message).into_val(env),
54
+ sub_invokes: &[],
55
+ },
56
+ }])
57
+ .clear(&receiver, &origin, &receiver, &guid, &message);
58
+
59
+ // Verify PacketDelivered event was emitted
60
+ assert_event(env, &endpoint_client.address, PacketDelivered { origin: origin.clone(), receiver: receiver.clone() });
61
+
62
+ // Verify payload hash is removed
63
+ let cleared = env.as_contract(&endpoint_client.address, || {
64
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender_bytes, nonce)
65
+ });
66
+ assert_eq!(cleared, None);
67
+
68
+ // Verify lazy nonce was updated
69
+ let lazy_nonce = env.as_contract(&endpoint_client.address, || {
70
+ storage::EndpointStorage::lazy_inbound_nonce(env, &receiver, src_eid, &sender_bytes)
71
+ });
72
+ assert_eq!(lazy_nonce, nonce);
73
+ }
74
+
75
+ #[test]
76
+ fn test_clear_with_delegate() {
77
+ let test_setup = setup();
78
+ let env = &test_setup.env;
79
+ let endpoint_client = &test_setup.endpoint_client;
80
+
81
+ let receiver = Address::generate(env);
82
+ let delegate = Address::generate(env);
83
+ let src_eid = 2;
84
+ let sender_bytes = BytesN::from_array(env, &[1u8; 32]);
85
+ let nonce = 1;
86
+ let message = Bytes::from_array(env, &[0xdd, 0xee, 0xff]);
87
+
88
+ // Set delegate for receiver
89
+ env.as_contract(&endpoint_client.address, || storage::EndpointStorage::set_delegate(env, &receiver, &delegate));
90
+
91
+ // Compute guid and build payload
92
+ let guid =
93
+ env.as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
94
+ let payload = env.as_contract(&endpoint_client.address, || build_payload(env, &guid, &message));
95
+
96
+ // Store payload hash
97
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
98
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
99
+ });
100
+ env.as_contract(&endpoint_client.address, || {
101
+ EndpointV2::inbound(env, &receiver, src_eid, &sender_bytes, nonce, &payload_hash)
102
+ });
103
+
104
+ // Clear using delegate
105
+ let origin = Origin { src_eid, sender: sender_bytes.clone(), nonce };
106
+ endpoint_client
107
+ .mock_auths(&[soroban_sdk::testutils::MockAuth {
108
+ address: &delegate,
109
+ invoke: &soroban_sdk::testutils::MockAuthInvoke {
110
+ contract: &endpoint_client.address,
111
+ fn_name: "clear",
112
+ args: (&delegate, &origin, &receiver, &guid, &message).into_val(env),
113
+ sub_invokes: &[],
114
+ },
115
+ }])
116
+ .clear(&delegate, &origin, &receiver, &guid, &message);
117
+
118
+ // Verify PacketDelivered event was emitted
119
+ assert_event(env, &endpoint_client.address, PacketDelivered { origin: origin.clone(), receiver: receiver.clone() });
120
+
121
+ // Verify payload is cleared
122
+ let cleared = env.as_contract(&endpoint_client.address, || {
123
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender_bytes, nonce)
124
+ });
125
+ assert_eq!(cleared, None);
126
+ }
127
+
128
+ #[test]
129
+ fn test_panic_clear_unauthorized() {
130
+ let test_setup = setup();
131
+ let env = &test_setup.env;
132
+ let endpoint_client = &test_setup.endpoint_client;
133
+
134
+ let receiver = Address::generate(env);
135
+ let unauthorized_caller = Address::generate(env);
136
+ let src_eid = 2;
137
+ let sender_bytes = BytesN::from_array(env, &[1u8; 32]);
138
+ let nonce = 1;
139
+ let message = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
140
+
141
+ let guid =
142
+ env.as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
143
+
144
+ let origin = Origin { src_eid, sender: sender_bytes.clone(), nonce };
145
+
146
+ // Try to clear with unauthorized caller - should panic
147
+ assert_eq!(
148
+ endpoint_client
149
+ .mock_auths(&[soroban_sdk::testutils::MockAuth {
150
+ address: &unauthorized_caller,
151
+ invoke: &soroban_sdk::testutils::MockAuthInvoke {
152
+ contract: &endpoint_client.address,
153
+ fn_name: "clear",
154
+ args: (&unauthorized_caller, &origin, &receiver, &guid, &message).into_val(env),
155
+ sub_invokes: &[],
156
+ },
157
+ }])
158
+ .try_clear(&unauthorized_caller, &origin, &receiver, &guid, &message)
159
+ .unwrap_err()
160
+ .unwrap(),
161
+ EndpointError::Unauthorized.into()
162
+ );
163
+ }
164
+
165
+ #[test]
166
+ fn test_panic_clear_wrong_message() {
167
+ let test_setup = setup();
168
+ let env = &test_setup.env;
169
+ let endpoint_client = &test_setup.endpoint_client;
170
+
171
+ let receiver = Address::generate(env);
172
+ let src_eid = 2;
173
+ let sender_bytes = BytesN::from_array(env, &[1u8; 32]);
174
+ let nonce = 1;
175
+ let correct_message = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
176
+ let wrong_message = Bytes::from_array(env, &[0xdd, 0xee, 0xff]);
177
+
178
+ // Store with correct message
179
+ let guid =
180
+ env.as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
181
+ let payload = env.as_contract(&endpoint_client.address, || build_payload(env, &guid, &correct_message));
182
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
183
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
184
+ });
185
+ env.as_contract(&endpoint_client.address, || {
186
+ EndpointV2::inbound(env, &receiver, src_eid, &sender_bytes, nonce, &payload_hash)
187
+ });
188
+
189
+ // Try to clear with wrong message - should panic
190
+ let origin = Origin { src_eid, sender: sender_bytes.clone(), nonce };
191
+ assert_eq!(
192
+ endpoint_client
193
+ .mock_auths(&[soroban_sdk::testutils::MockAuth {
194
+ address: &receiver,
195
+ invoke: &soroban_sdk::testutils::MockAuthInvoke {
196
+ contract: &endpoint_client.address,
197
+ fn_name: "clear",
198
+ args: (&receiver, &origin, &receiver, &guid, &wrong_message).into_val(env),
199
+ sub_invokes: &[],
200
+ },
201
+ }])
202
+ .try_clear(&receiver, &origin, &receiver, &guid, &wrong_message)
203
+ .unwrap_err()
204
+ .unwrap(),
205
+ EndpointError::PayloadHashNotFound.into()
206
+ );
207
+ }
208
+
209
+ #[test]
210
+ fn test_panic_clear_wrong_guid() {
211
+ let test_setup = setup();
212
+ let env = &test_setup.env;
213
+ let endpoint_client = &test_setup.endpoint_client;
214
+
215
+ let receiver = Address::generate(env);
216
+ let src_eid = 2;
217
+ let sender_bytes = BytesN::from_array(env, &[1u8; 32]);
218
+ let nonce = 1;
219
+ let message = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
220
+
221
+ // Store with correct guid
222
+ let correct_guid =
223
+ env.as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
224
+ let payload = env.as_contract(&endpoint_client.address, || build_payload(env, &correct_guid, &message));
225
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
226
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
227
+ });
228
+ env.as_contract(&endpoint_client.address, || {
229
+ EndpointV2::inbound(env, &receiver, src_eid, &sender_bytes, nonce, &payload_hash)
230
+ });
231
+
232
+ // Try to clear with wrong guid - should panic
233
+ let wrong_guid = BytesN::from_array(env, &[0xffu8; 32]);
234
+ let origin = Origin { src_eid, sender: sender_bytes.clone(), nonce };
235
+ assert_eq!(
236
+ endpoint_client
237
+ .mock_auths(&[soroban_sdk::testutils::MockAuth {
238
+ address: &receiver,
239
+ invoke: &soroban_sdk::testutils::MockAuthInvoke {
240
+ contract: &endpoint_client.address,
241
+ fn_name: "clear",
242
+ args: (&receiver, &origin, &receiver, &wrong_guid, &message).into_val(env),
243
+ sub_invokes: &[],
244
+ },
245
+ }])
246
+ .try_clear(&receiver, &origin, &receiver, &wrong_guid, &message)
247
+ .unwrap_err()
248
+ .unwrap(),
249
+ EndpointError::PayloadHashNotFound.into()
250
+ );
251
+ }
252
+
253
+ #[test]
254
+ fn test_clear_multiple_sequential() {
255
+ let test_setup = setup();
256
+ let env = &test_setup.env;
257
+ let endpoint_client = &test_setup.endpoint_client;
258
+
259
+ let receiver = Address::generate(env);
260
+ let src_eid = 2;
261
+ let sender_bytes = BytesN::from_array(env, &[1u8; 32]);
262
+
263
+ // Store 3 payloads
264
+ for nonce in 1..=3 {
265
+ let message = Bytes::from_array(env, &[nonce as u8]);
266
+ let guid = env
267
+ .as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
268
+ let payload = env.as_contract(&endpoint_client.address, || build_payload(env, &guid, &message));
269
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
270
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
271
+ });
272
+ env.as_contract(&endpoint_client.address, || {
273
+ EndpointV2::inbound(env, &receiver, src_eid, &sender_bytes, nonce, &payload_hash)
274
+ });
275
+ }
276
+
277
+ // Clear them in order
278
+ for nonce in 1..=3 {
279
+ let message = Bytes::from_array(env, &[nonce as u8]);
280
+ let guid = env
281
+ .as_contract(&endpoint_client.address, || compute_guid(env, nonce, src_eid, &receiver, 1, &sender_bytes));
282
+ let origin = Origin { src_eid, sender: sender_bytes.clone(), nonce };
283
+
284
+ endpoint_client
285
+ .mock_auths(&[soroban_sdk::testutils::MockAuth {
286
+ address: &receiver,
287
+ invoke: &soroban_sdk::testutils::MockAuthInvoke {
288
+ contract: &endpoint_client.address,
289
+ fn_name: "clear",
290
+ args: (&receiver, &origin, &receiver, &guid, &message).into_val(env),
291
+ sub_invokes: &[],
292
+ },
293
+ }])
294
+ .clear(&receiver, &origin, &receiver, &guid, &message);
295
+ }
296
+
297
+ // Verify all are cleared
298
+ for nonce in 1..=3 {
299
+ let cleared = env.as_contract(&endpoint_client.address, || {
300
+ storage::EndpointStorage::inbound_payload_hash(
301
+ env,
302
+ &receiver,
303
+ src_eid,
304
+ &sender_bytes,
305
+ nonce,
306
+ )
307
+ });
308
+ assert_eq!(cleared, None);
309
+ }
310
+
311
+ // Verify lazy nonce is updated to 3
312
+ let lazy_nonce = env.as_contract(&endpoint_client.address, || {
313
+ storage::EndpointStorage::lazy_inbound_nonce(env, &receiver, src_eid, &sender_bytes)
314
+ });
315
+ assert_eq!(lazy_nonce, 3);
316
+ }
@@ -0,0 +1,288 @@
1
+ use soroban_sdk::{testutils::Address as _, Address, BytesN};
2
+
3
+ use crate::{endpoint_v2::EndpointV2, storage, tests::endpoint_setup::setup};
4
+
5
+ #[test]
6
+ fn test_inbound_nonce_initial_value() {
7
+ let test_setup = setup();
8
+ let env = &test_setup.env;
9
+ let endpoint_client = &test_setup.endpoint_client;
10
+
11
+ let receiver = Address::generate(env);
12
+ let src_eid = 2;
13
+ let sender = BytesN::from_array(env, &[1u8; 32]);
14
+
15
+ // Initial inbound nonce should be 0 (lazy nonce is 0, no payload hashes)
16
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
17
+ assert_eq!(nonce, 0);
18
+ }
19
+
20
+ #[test]
21
+ fn test_inbound_nonce_with_lazy_nonce_only() {
22
+ let test_setup = setup();
23
+ let env = &test_setup.env;
24
+ let endpoint_client = &test_setup.endpoint_client;
25
+
26
+ let receiver = Address::generate(env);
27
+ let src_eid = 2;
28
+ let sender = BytesN::from_array(env, &[1u8; 32]);
29
+ let lazy_nonce = 5;
30
+
31
+ // Set lazy nonce without any payload hashes
32
+ env.as_contract(&endpoint_client.address, || {
33
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &lazy_nonce)
34
+ });
35
+
36
+ // Inbound nonce should equal lazy nonce when no payload hashes exist
37
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
38
+ assert_eq!(nonce, lazy_nonce);
39
+ }
40
+
41
+ #[test]
42
+ fn test_inbound_nonce_with_consecutive_payload_hashes() {
43
+ let test_setup = setup();
44
+ let env = &test_setup.env;
45
+ let endpoint_client = &test_setup.endpoint_client;
46
+
47
+ let receiver = Address::generate(env);
48
+ let src_eid = 2;
49
+ let sender = BytesN::from_array(env, &[1u8; 32]);
50
+ let lazy_nonce = 2;
51
+
52
+ // Set lazy nonce to 2
53
+ env.as_contract(&endpoint_client.address, || {
54
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &lazy_nonce)
55
+ });
56
+
57
+ // Add consecutive payload hashes starting from lazy_nonce + 1
58
+ let payload_hash1 = BytesN::from_array(env, &[0xabu8; 32]);
59
+ let payload_hash2 = BytesN::from_array(env, &[0xcdu8; 32]);
60
+ let payload_hash3 = BytesN::from_array(env, &[0xefu8; 32]);
61
+
62
+ env.as_contract(&endpoint_client.address, || {
63
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 3, &payload_hash1)
64
+ });
65
+ env.as_contract(&endpoint_client.address, || {
66
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 4, &payload_hash2)
67
+ });
68
+ env.as_contract(&endpoint_client.address, || {
69
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 5, &payload_hash3)
70
+ });
71
+
72
+ // Inbound nonce should be 5 (lazy_nonce + 3 consecutive payload hashes)
73
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
74
+ assert_eq!(nonce, 5);
75
+ }
76
+
77
+ #[test]
78
+ fn test_inbound_nonce_with_gap_in_payload_hashes() {
79
+ let test_setup = setup();
80
+ let env = &test_setup.env;
81
+ let endpoint_client = &test_setup.endpoint_client;
82
+
83
+ let receiver = Address::generate(env);
84
+ let src_eid = 2;
85
+ let sender = BytesN::from_array(env, &[1u8; 32]);
86
+ let lazy_nonce = 2;
87
+
88
+ // Set lazy nonce to 2
89
+ env.as_contract(&endpoint_client.address, || {
90
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &lazy_nonce)
91
+ });
92
+
93
+ // Add payload hashes with a gap (nonce 3 and 5, but not 4)
94
+ let payload_hash1 = BytesN::from_array(env, &[0xabu8; 32]);
95
+ let payload_hash2 = BytesN::from_array(env, &[0xcdu8; 32]);
96
+
97
+ env.as_contract(&endpoint_client.address, || {
98
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 3, &payload_hash1)
99
+ });
100
+ env.as_contract(&endpoint_client.address, || {
101
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 5, &payload_hash2)
102
+ });
103
+
104
+ // Inbound nonce should be 3 (stops at first gap)
105
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
106
+ assert_eq!(nonce, 3);
107
+ }
108
+
109
+ #[test]
110
+ fn test_inbound_nonce_with_zero_lazy_nonce_and_payload_hashes() {
111
+ let test_setup = setup();
112
+ let env = &test_setup.env;
113
+ let endpoint_client = &test_setup.endpoint_client;
114
+
115
+ let receiver = Address::generate(env);
116
+ let src_eid = 2;
117
+ let sender = BytesN::from_array(env, &[1u8; 32]);
118
+
119
+ // Lazy nonce is 0 by default
120
+ // Add consecutive payload hashes starting from 1
121
+ let payload_hash1 = BytesN::from_array(env, &[0xabu8; 32]);
122
+ let payload_hash2 = BytesN::from_array(env, &[0xcdu8; 32]);
123
+
124
+ env.as_contract(&endpoint_client.address, || {
125
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 1, &payload_hash1)
126
+ });
127
+ env.as_contract(&endpoint_client.address, || {
128
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 2, &payload_hash2)
129
+ });
130
+
131
+ // Inbound nonce should be 2 (0 + 2 consecutive payload hashes)
132
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
133
+ assert_eq!(nonce, 2);
134
+ }
135
+
136
+ #[test]
137
+ fn test_inbound_nonce_different_paths() {
138
+ let test_setup = setup();
139
+ let env = &test_setup.env;
140
+ let endpoint_client = &test_setup.endpoint_client;
141
+
142
+ let receiver1 = Address::generate(env);
143
+ let receiver2 = Address::generate(env);
144
+ let src_eid1 = 2;
145
+ let src_eid2 = 3;
146
+ let sender1 = BytesN::from_array(env, &[1u8; 32]);
147
+ let sender2 = BytesN::from_array(env, &[2u8; 32]);
148
+
149
+ // Set different lazy nonces for different paths
150
+ env.as_contract(&endpoint_client.address, || {
151
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid1, &sender1, &10)
152
+ });
153
+ env.as_contract(&endpoint_client.address, || {
154
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver2, src_eid1, &sender1, &20)
155
+ });
156
+ env.as_contract(&endpoint_client.address, || {
157
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid2, &sender1, &30)
158
+ });
159
+ env.as_contract(&endpoint_client.address, || {
160
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid1, &sender2, &40)
161
+ });
162
+
163
+ // Add payload hashes for some paths
164
+ let payload_hash = BytesN::from_array(env, &[0xabu8; 32]);
165
+
166
+ // Add payload hash for receiver1, src_eid1, sender1 (nonce 11)
167
+ env.as_contract(&endpoint_client.address, || {
168
+ EndpointV2::inbound(env, &receiver1, src_eid1, &sender1, 11, &payload_hash)
169
+ });
170
+
171
+ // Add payload hash for receiver1, src_eid2, sender1 (nonce 31 and 32)
172
+ env.as_contract(&endpoint_client.address, || {
173
+ EndpointV2::inbound(env, &receiver1, src_eid2, &sender1, 31, &payload_hash)
174
+ });
175
+ env.as_contract(&endpoint_client.address, || {
176
+ EndpointV2::inbound(env, &receiver1, src_eid2, &sender1, 32, &payload_hash)
177
+ });
178
+
179
+ // Verify each path has independent inbound nonce calculation
180
+ let nonce1 = endpoint_client.inbound_nonce(&receiver1, &src_eid1, &sender1);
181
+ let nonce2 = endpoint_client.inbound_nonce(&receiver2, &src_eid1, &sender1);
182
+ let nonce3 = endpoint_client.inbound_nonce(&receiver1, &src_eid2, &sender1);
183
+ let nonce4 = endpoint_client.inbound_nonce(&receiver1, &src_eid1, &sender2);
184
+
185
+ assert_eq!(nonce1, 11); // lazy_nonce 10 + 1 payload hash
186
+ assert_eq!(nonce2, 20); // lazy_nonce 20, no payload hashes
187
+ assert_eq!(nonce3, 32); // lazy_nonce 30 + 2 consecutive payload hashes
188
+ assert_eq!(nonce4, 40); // lazy_nonce 40, no payload hashes
189
+ }
190
+
191
+ #[test]
192
+ fn test_inbound_nonce_large_consecutive_sequence() {
193
+ let test_setup = setup();
194
+ let env = &test_setup.env;
195
+ let endpoint_client = &test_setup.endpoint_client;
196
+
197
+ let receiver = Address::generate(env);
198
+ let src_eid = 2;
199
+ let sender = BytesN::from_array(env, &[1u8; 32]);
200
+ let lazy_nonce = 100;
201
+ let sequence_length = 50;
202
+
203
+ // Set lazy nonce
204
+ env.as_contract(&endpoint_client.address, || {
205
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &lazy_nonce)
206
+ });
207
+
208
+ // Add a long sequence of consecutive payload hashes
209
+ let payload_hash = BytesN::from_array(env, &[0xabu8; 32]);
210
+ for i in 1..=sequence_length {
211
+ env.as_contract(&endpoint_client.address, || {
212
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, lazy_nonce + i, &payload_hash)
213
+ });
214
+ }
215
+
216
+ // Inbound nonce should be lazy_nonce + sequence_length
217
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
218
+ assert_eq!(nonce, lazy_nonce + sequence_length);
219
+ }
220
+
221
+ #[test]
222
+ fn test_inbound_nonce_after_payload_removal() {
223
+ let test_setup = setup();
224
+ let env = &test_setup.env;
225
+ let endpoint_client = &test_setup.endpoint_client;
226
+
227
+ let receiver = Address::generate(env);
228
+ let src_eid = 2;
229
+ let sender = BytesN::from_array(env, &[1u8; 32]);
230
+ let lazy_nonce = 5;
231
+
232
+ // Set lazy nonce
233
+ env.as_contract(&endpoint_client.address, || {
234
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &lazy_nonce)
235
+ });
236
+
237
+ // Add consecutive payload hashes
238
+ let payload_hash = BytesN::from_array(env, &[0xabu8; 32]);
239
+ env.as_contract(&endpoint_client.address, || {
240
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 6, &payload_hash)
241
+ });
242
+ env.as_contract(&endpoint_client.address, || {
243
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 7, &payload_hash)
244
+ });
245
+ env.as_contract(&endpoint_client.address, || {
246
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 8, &payload_hash)
247
+ });
248
+
249
+ // Verify inbound nonce is 8
250
+ let nonce_before = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
251
+ assert_eq!(nonce_before, 8);
252
+
253
+ // Remove payload hash at nonce 7 (creates a gap)
254
+ env.as_contract(&endpoint_client.address, || {
255
+ storage::EndpointStorage::remove_inbound_payload_hash(env, &receiver, src_eid, &sender, 7)
256
+ });
257
+
258
+ // Inbound nonce should now be 6 (stops at the gap)
259
+ let nonce_after = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
260
+ assert_eq!(nonce_after, 6);
261
+ }
262
+
263
+ #[test]
264
+ fn test_inbound_nonce_no_payload_hash_at_lazy_nonce_plus_one() {
265
+ let test_setup = setup();
266
+ let env = &test_setup.env;
267
+ let endpoint_client = &test_setup.endpoint_client;
268
+
269
+ let receiver = Address::generate(env);
270
+ let src_eid = 2;
271
+ let sender = BytesN::from_array(env, &[1u8; 32]);
272
+ let lazy_nonce = 10;
273
+
274
+ // Set lazy nonce
275
+ env.as_contract(&endpoint_client.address, || {
276
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &lazy_nonce)
277
+ });
278
+
279
+ // Add payload hash at nonce 12 (skipping nonce 11)
280
+ let payload_hash = BytesN::from_array(env, &[0xabu8; 32]);
281
+ env.as_contract(&endpoint_client.address, || {
282
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, 12, &payload_hash)
283
+ });
284
+
285
+ // Inbound nonce should remain at lazy_nonce (no consecutive sequence from lazy_nonce + 1)
286
+ let nonce = endpoint_client.inbound_nonce(&receiver, &src_eid, &sender);
287
+ assert_eq!(nonce, lazy_nonce);
288
+ }