@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,388 @@
1
+ use soroban_sdk::{testutils::Address as _, Address, Bytes, BytesN};
2
+
3
+ use crate::{endpoint_v2::EndpointV2, storage, tests::endpoint_setup::setup};
4
+
5
+ // ============================================================================
6
+ // Tests for outbound function
7
+ // ============================================================================
8
+
9
+ #[test]
10
+ fn test_outbound() {
11
+ let test_setup = setup();
12
+ let env = &test_setup.env;
13
+ let endpoint_client = &test_setup.endpoint_client;
14
+
15
+ let sender = Address::generate(env);
16
+ let dst_eid = 2;
17
+ let receiver = BytesN::from_array(env, &[1u8; 32]);
18
+
19
+ // First call should return nonce 1
20
+ let nonce1 = env.as_contract(&endpoint_client.address, || EndpointV2::outbound(env, &sender, dst_eid, &receiver));
21
+ assert_eq!(nonce1, 1);
22
+
23
+ // Second call should return nonce 2
24
+ let nonce2 = env.as_contract(&endpoint_client.address, || EndpointV2::outbound(env, &sender, dst_eid, &receiver));
25
+ assert_eq!(nonce2, 2);
26
+
27
+ // Third call should return nonce 3
28
+ let nonce3 = env.as_contract(&endpoint_client.address, || EndpointV2::outbound(env, &sender, dst_eid, &receiver));
29
+ assert_eq!(nonce3, 3);
30
+
31
+ // Different sender should have independent nonce counter (starts at 1)
32
+ let different_sender = Address::generate(env);
33
+ let nonce_diff_sender =
34
+ env.as_contract(&endpoint_client.address, || EndpointV2::outbound(env, &different_sender, dst_eid, &receiver));
35
+ assert_eq!(nonce_diff_sender, 1);
36
+
37
+ // Different dst_eid should have independent nonce counter (starts at 1)
38
+ let different_dst_eid = 3;
39
+ let nonce_diff_dst =
40
+ env.as_contract(&endpoint_client.address, || EndpointV2::outbound(env, &sender, different_dst_eid, &receiver));
41
+ assert_eq!(nonce_diff_dst, 1);
42
+
43
+ // Different receiver should have independent nonce counter (starts at 1)
44
+ let different_receiver = BytesN::from_array(env, &[2u8; 32]);
45
+ let nonce_diff_receiver =
46
+ env.as_contract(&endpoint_client.address, || EndpointV2::outbound(env, &sender, dst_eid, &different_receiver));
47
+ assert_eq!(nonce_diff_receiver, 1);
48
+
49
+ // Verify storage was updated correctly for original path
50
+ let stored_nonce = env.as_contract(&endpoint_client.address, || {
51
+ storage::EndpointStorage::outbound_nonce(env, &sender, dst_eid, &receiver)
52
+ });
53
+ assert_eq!(stored_nonce, 3);
54
+ }
55
+
56
+ // ============================================================================
57
+ // Tests for inbound function
58
+ // ============================================================================
59
+
60
+ #[test]
61
+ fn test_inbound_success() {
62
+ let test_setup = setup();
63
+ let env = &test_setup.env;
64
+ let endpoint_client = &test_setup.endpoint_client;
65
+
66
+ let receiver = Address::generate(env);
67
+ let src_eid = 2;
68
+ let sender = BytesN::from_array(env, &[1u8; 32]);
69
+ let nonce = 1;
70
+ let payload_hash = BytesN::from_array(env, &[0xabu8; 32]); // Valid non-empty payload hash
71
+
72
+ // Call inbound with non-empty payload hash - should succeed
73
+ env.as_contract(&endpoint_client.address, || {
74
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, nonce, &payload_hash)
75
+ });
76
+
77
+ // Verify storage was updated correctly
78
+ let stored_hash = env.as_contract(&endpoint_client.address, || {
79
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, nonce)
80
+ });
81
+ assert_eq!(stored_hash, Some(payload_hash.clone()));
82
+
83
+ // Test with different nonce for same path
84
+ let nonce2 = 2;
85
+ let payload_hash2 = BytesN::from_array(env, &[0xcdu8; 32]); // Different payload hash
86
+ env.as_contract(&endpoint_client.address, || {
87
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, nonce2, &payload_hash2)
88
+ });
89
+
90
+ let stored_hash2 = env.as_contract(&endpoint_client.address, || {
91
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, nonce2)
92
+ });
93
+ assert_eq!(stored_hash2, Some(payload_hash2.clone()));
94
+
95
+ // Test with different receiver - should have independent storage
96
+ let different_receiver = Address::generate(env);
97
+ let payload_hash3 = BytesN::from_array(env, &[0xefu8; 32]);
98
+ env.as_contract(&endpoint_client.address, || {
99
+ EndpointV2::inbound(env, &different_receiver, src_eid, &sender, nonce, &payload_hash3)
100
+ });
101
+
102
+ let stored_hash_diff = env.as_contract(&endpoint_client.address, || {
103
+ storage::EndpointStorage::inbound_payload_hash(
104
+ env,
105
+ &different_receiver,
106
+ src_eid,
107
+ &sender,
108
+ nonce,
109
+ )
110
+ });
111
+ assert_eq!(stored_hash_diff, Some(payload_hash3.clone()));
112
+
113
+ // Original receiver's storage should be unchanged
114
+ let original_hash = env.as_contract(&endpoint_client.address, || {
115
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, nonce)
116
+ });
117
+ assert_eq!(original_hash, Some(payload_hash));
118
+ }
119
+
120
+ #[test]
121
+ #[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidPayloadHash
122
+ fn test_inbound_empty_payload_hash() {
123
+ let test_setup = setup();
124
+ let env = &test_setup.env;
125
+ let endpoint_client = &test_setup.endpoint_client;
126
+
127
+ let receiver = Address::generate(env);
128
+ let src_eid = 2;
129
+ let sender = BytesN::from_array(env, &[1u8; 32]);
130
+ let nonce = 1;
131
+ let empty_hash = BytesN::from_array(env, &[0u8; 32]); // empty_payload_hash - now invalid
132
+
133
+ // Should panic with InvalidPayloadHash error because empty hash is not allowed
134
+ env.as_contract(&endpoint_client.address, || {
135
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, nonce, &empty_hash)
136
+ });
137
+ }
138
+
139
+ // ============================================================================
140
+ // Tests for clear_payload function
141
+ // ============================================================================
142
+
143
+ #[test]
144
+ fn test_clear_payload_success() {
145
+ let test_setup = setup();
146
+ let env = &test_setup.env;
147
+ let endpoint_client = &test_setup.endpoint_client;
148
+
149
+ let receiver = Address::generate(env);
150
+ let src_eid = 2;
151
+ let sender = BytesN::from_array(env, &[1u8; 32]);
152
+ let nonce = 1;
153
+ let payload = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
154
+
155
+ // Compute the expected hash
156
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
157
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
158
+ });
159
+
160
+ // First store the payload hash via inbound
161
+ env.as_contract(&endpoint_client.address, || {
162
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, nonce, &payload_hash)
163
+ });
164
+
165
+ // Verify it's stored
166
+ let stored_hash = env.as_contract(&endpoint_client.address, || {
167
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, nonce)
168
+ });
169
+ assert_eq!(stored_hash, Some(payload_hash.clone()));
170
+
171
+ // Clear the payload
172
+ env.as_contract(&endpoint_client.address, || {
173
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, nonce, &payload)
174
+ });
175
+
176
+ // Verify it's removed from storage
177
+ let cleared_hash = env.as_contract(&endpoint_client.address, || {
178
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, nonce)
179
+ });
180
+ assert_eq!(cleared_hash, None);
181
+
182
+ // Verify lazy nonce was updated
183
+ let lazy_nonce = env.as_contract(&endpoint_client.address, || {
184
+ storage::EndpointStorage::lazy_inbound_nonce(env, &receiver, src_eid, &sender)
185
+ });
186
+ assert_eq!(lazy_nonce, nonce);
187
+ }
188
+
189
+ #[test]
190
+ fn test_clear_payload_with_lazy_nonce_update() {
191
+ let test_setup = setup();
192
+ let env = &test_setup.env;
193
+ let endpoint_client = &test_setup.endpoint_client;
194
+
195
+ let receiver = Address::generate(env);
196
+ let src_eid = 2;
197
+ let sender = BytesN::from_array(env, &[1u8; 32]);
198
+
199
+ // Store three payloads (nonce 1, 2, 3)
200
+ let payload1 = Bytes::from_array(env, &[0x01]);
201
+ let payload2 = Bytes::from_array(env, &[0x02]);
202
+ let payload3 = Bytes::from_array(env, &[0x03]);
203
+
204
+ let hash1 = env.as_contract(&endpoint_client.address, || {
205
+ BytesN::from_array(env, &env.crypto().keccak256(&payload1).to_array())
206
+ });
207
+ let hash2 = env.as_contract(&endpoint_client.address, || {
208
+ BytesN::from_array(env, &env.crypto().keccak256(&payload2).to_array())
209
+ });
210
+ let hash3 = env.as_contract(&endpoint_client.address, || {
211
+ BytesN::from_array(env, &env.crypto().keccak256(&payload3).to_array())
212
+ });
213
+
214
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 1, &hash1));
215
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 2, &hash2));
216
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 3, &hash3));
217
+
218
+ // Lazy nonce should be 0 (not updated yet)
219
+ let lazy_nonce = env.as_contract(&endpoint_client.address, || {
220
+ storage::EndpointStorage::lazy_inbound_nonce(env, &receiver, src_eid, &sender)
221
+ });
222
+ assert_eq!(lazy_nonce, 0);
223
+
224
+ // Clear payload 3 directly (skipping 1 and 2)
225
+ env.as_contract(&endpoint_client.address, || {
226
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, 3, &payload3)
227
+ });
228
+
229
+ // Lazy nonce should be updated to 3
230
+ let lazy_nonce = env.as_contract(&endpoint_client.address, || {
231
+ storage::EndpointStorage::lazy_inbound_nonce(env, &receiver, src_eid, &sender)
232
+ });
233
+ assert_eq!(lazy_nonce, 3);
234
+
235
+ // Payload 3 should be cleared
236
+ let hash3_after = env.as_contract(&endpoint_client.address, || {
237
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, 3)
238
+ });
239
+ assert_eq!(hash3_after, None);
240
+ }
241
+
242
+ #[test]
243
+ fn test_clear_payload_sequential() {
244
+ let test_setup = setup();
245
+ let env = &test_setup.env;
246
+ let endpoint_client = &test_setup.endpoint_client;
247
+
248
+ let receiver = Address::generate(env);
249
+ let src_eid = 2;
250
+ let sender = BytesN::from_array(env, &[1u8; 32]);
251
+
252
+ // Store three payloads
253
+ let payload1 = Bytes::from_array(env, &[0x01]);
254
+ let payload2 = Bytes::from_array(env, &[0x02]);
255
+ let payload3 = Bytes::from_array(env, &[0x03]);
256
+
257
+ let hash1 = env.as_contract(&endpoint_client.address, || {
258
+ BytesN::from_array(env, &env.crypto().keccak256(&payload1).to_array())
259
+ });
260
+ let hash2 = env.as_contract(&endpoint_client.address, || {
261
+ BytesN::from_array(env, &env.crypto().keccak256(&payload2).to_array())
262
+ });
263
+ let hash3 = env.as_contract(&endpoint_client.address, || {
264
+ BytesN::from_array(env, &env.crypto().keccak256(&payload3).to_array())
265
+ });
266
+
267
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 1, &hash1));
268
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 2, &hash2));
269
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 3, &hash3));
270
+
271
+ // Clear them in order: 1, 2, 3
272
+ env.as_contract(&endpoint_client.address, || {
273
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, 1, &payload1)
274
+ });
275
+ env.as_contract(&endpoint_client.address, || {
276
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, 2, &payload2)
277
+ });
278
+ env.as_contract(&endpoint_client.address, || {
279
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, 3, &payload3)
280
+ });
281
+
282
+ // All should be cleared
283
+ let hash1_after = env.as_contract(&endpoint_client.address, || {
284
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, 1)
285
+ });
286
+ let hash2_after = env.as_contract(&endpoint_client.address, || {
287
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, 2)
288
+ });
289
+ let hash3_after = env.as_contract(&endpoint_client.address, || {
290
+ storage::EndpointStorage::inbound_payload_hash(env, &receiver, src_eid, &sender, 3)
291
+ });
292
+
293
+ assert_eq!(hash1_after, None);
294
+ assert_eq!(hash2_after, None);
295
+ assert_eq!(hash3_after, None);
296
+
297
+ // Lazy nonce should be 3
298
+ let lazy_nonce = env.as_contract(&endpoint_client.address, || {
299
+ storage::EndpointStorage::lazy_inbound_nonce(env, &receiver, src_eid, &sender)
300
+ });
301
+ assert_eq!(lazy_nonce, 3);
302
+ }
303
+
304
+ #[test]
305
+ #[should_panic(expected = "Error(Contract, #19)")] // EndpointError::PayloadHashNotFound
306
+ fn test_clear_payload_wrong_payload() {
307
+ let test_setup = setup();
308
+ let env = &test_setup.env;
309
+ let endpoint_client = &test_setup.endpoint_client;
310
+
311
+ let receiver = Address::generate(env);
312
+ let src_eid = 2;
313
+ let sender = BytesN::from_array(env, &[1u8; 32]);
314
+ let nonce = 1;
315
+
316
+ let payload = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
317
+ let wrong_payload = Bytes::from_array(env, &[0xdd, 0xee, 0xff]); // Different payload
318
+
319
+ let payload_hash = env.as_contract(&endpoint_client.address, || {
320
+ BytesN::from_array(env, &env.crypto().keccak256(&payload).to_array())
321
+ });
322
+
323
+ // Store the correct hash
324
+ env.as_contract(&endpoint_client.address, || {
325
+ EndpointV2::inbound(env, &receiver, src_eid, &sender, nonce, &payload_hash)
326
+ });
327
+
328
+ // Try to clear with wrong payload - should panic
329
+ env.as_contract(&endpoint_client.address, || {
330
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, nonce, &wrong_payload)
331
+ });
332
+ }
333
+
334
+ #[test]
335
+ #[should_panic(expected = "Error(Contract, #10)")] // EndpointError::InvalidNonce
336
+ fn test_clear_payload_not_stored() {
337
+ let test_setup = setup();
338
+ let env = &test_setup.env;
339
+ let endpoint_client = &test_setup.endpoint_client;
340
+
341
+ let receiver = Address::generate(env);
342
+ let src_eid = 2;
343
+ let sender = BytesN::from_array(env, &[1u8; 32]);
344
+ let nonce = 1;
345
+ let payload = Bytes::from_array(env, &[0xaa, 0xbb, 0xcc]);
346
+
347
+ // Try to clear without storing first - should panic with InvalidNonce
348
+ // (because intermediate nonce validation fails before checking payload hash)
349
+ env.as_contract(&endpoint_client.address, || {
350
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, nonce, &payload)
351
+ });
352
+ }
353
+
354
+ #[test]
355
+ #[should_panic(expected = "Error(Contract, #10)")] // EndpointError::InvalidNonce
356
+ fn test_clear_payload_missing_intermediate_nonce() {
357
+ let test_setup = setup();
358
+ let env = &test_setup.env;
359
+ let endpoint_client = &test_setup.endpoint_client;
360
+
361
+ let receiver = Address::generate(env);
362
+ let src_eid = 2;
363
+ let sender = BytesN::from_array(env, &[1u8; 32]);
364
+
365
+ // Store only nonce 1 and 3, skip nonce 2
366
+ let payload1 = Bytes::from_array(env, &[0x01]);
367
+ let payload3 = Bytes::from_array(env, &[0x03]);
368
+
369
+ let hash1 = env.as_contract(&endpoint_client.address, || {
370
+ BytesN::from_array(env, &env.crypto().keccak256(&payload1).to_array())
371
+ });
372
+ let hash3 = env.as_contract(&endpoint_client.address, || {
373
+ BytesN::from_array(env, &env.crypto().keccak256(&payload3).to_array())
374
+ });
375
+
376
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 1, &hash1));
377
+ env.as_contract(&endpoint_client.address, || EndpointV2::inbound(env, &receiver, src_eid, &sender, 3, &hash3));
378
+
379
+ // Clear nonce 1 first
380
+ env.as_contract(&endpoint_client.address, || {
381
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, 1, &payload1)
382
+ });
383
+
384
+ // Try to clear nonce 3 - should panic because nonce 2 is missing
385
+ env.as_contract(&endpoint_client.address, || {
386
+ EndpointV2::clear_payload(env, &receiver, src_eid, &sender, 3, &payload3)
387
+ });
388
+ }
@@ -0,0 +1,307 @@
1
+ use soroban_sdk::{testutils::Address as _, Address, BytesN};
2
+
3
+ use crate::{storage, tests::endpoint_setup::setup};
4
+
5
+ #[test]
6
+ fn test_lazy_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 lazy inbound nonce should be 0
16
+ let nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
17
+ assert_eq!(nonce, 0);
18
+ }
19
+
20
+ #[test]
21
+ fn test_lazy_inbound_nonce_after_setting() {
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 expected_nonce = 42;
30
+
31
+ // Set lazy inbound nonce
32
+ env.as_contract(&endpoint_client.address, || {
33
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &expected_nonce)
34
+ });
35
+
36
+ // Verify lazy inbound nonce is retrieved correctly
37
+ let nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
38
+ assert_eq!(nonce, expected_nonce);
39
+ }
40
+
41
+ #[test]
42
+ fn test_lazy_inbound_nonce_different_receivers() {
43
+ let test_setup = setup();
44
+ let env = &test_setup.env;
45
+ let endpoint_client = &test_setup.endpoint_client;
46
+
47
+ let receiver1 = Address::generate(env);
48
+ let receiver2 = Address::generate(env);
49
+ let src_eid = 2;
50
+ let sender = BytesN::from_array(env, &[1u8; 32]);
51
+
52
+ // Set different nonces for different receivers
53
+ let nonce1 = 10;
54
+ let nonce2 = 20;
55
+
56
+ env.as_contract(&endpoint_client.address, || {
57
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid, &sender, &nonce1)
58
+ });
59
+ env.as_contract(&endpoint_client.address, || {
60
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver2, src_eid, &sender, &nonce2)
61
+ });
62
+
63
+ // Verify each receiver has its own independent lazy nonce
64
+ let retrieved_nonce1 = endpoint_client.lazy_inbound_nonce(&receiver1, &src_eid, &sender);
65
+ let retrieved_nonce2 = endpoint_client.lazy_inbound_nonce(&receiver2, &src_eid, &sender);
66
+
67
+ assert_eq!(retrieved_nonce1, nonce1);
68
+ assert_eq!(retrieved_nonce2, nonce2);
69
+
70
+ // Verify a third receiver still has initial nonce of 0
71
+ let receiver3 = Address::generate(env);
72
+ let retrieved_nonce3 = endpoint_client.lazy_inbound_nonce(&receiver3, &src_eid, &sender);
73
+ assert_eq!(retrieved_nonce3, 0);
74
+ }
75
+
76
+ #[test]
77
+ fn test_lazy_inbound_nonce_different_src_eids() {
78
+ let test_setup = setup();
79
+ let env = &test_setup.env;
80
+ let endpoint_client = &test_setup.endpoint_client;
81
+
82
+ let receiver = Address::generate(env);
83
+ let src_eid1 = 2;
84
+ let src_eid2 = 3;
85
+ let sender = BytesN::from_array(env, &[1u8; 32]);
86
+
87
+ // Set different nonces for different source EIDs
88
+ let nonce1 = 15;
89
+ let nonce2 = 25;
90
+
91
+ env.as_contract(&endpoint_client.address, || {
92
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid1, &sender, &nonce1)
93
+ });
94
+ env.as_contract(&endpoint_client.address, || {
95
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid2, &sender, &nonce2)
96
+ });
97
+
98
+ // Verify each src_eid has its own independent lazy nonce
99
+ let retrieved_nonce1 = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid1, &sender);
100
+ let retrieved_nonce2 = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid2, &sender);
101
+
102
+ assert_eq!(retrieved_nonce1, nonce1);
103
+ assert_eq!(retrieved_nonce2, nonce2);
104
+
105
+ // Verify a third src_eid still has initial nonce of 0
106
+ let src_eid3 = 4;
107
+ let retrieved_nonce3 = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid3, &sender);
108
+ assert_eq!(retrieved_nonce3, 0);
109
+ }
110
+
111
+ #[test]
112
+ fn test_lazy_inbound_nonce_different_senders() {
113
+ let test_setup = setup();
114
+ let env = &test_setup.env;
115
+ let endpoint_client = &test_setup.endpoint_client;
116
+
117
+ let receiver = Address::generate(env);
118
+ let src_eid = 2;
119
+ let sender1 = BytesN::from_array(env, &[1u8; 32]);
120
+ let sender2 = BytesN::from_array(env, &[2u8; 32]);
121
+
122
+ // Set different nonces for different senders
123
+ let nonce1 = 30;
124
+ let nonce2 = 40;
125
+
126
+ env.as_contract(&endpoint_client.address, || {
127
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender1, &nonce1)
128
+ });
129
+ env.as_contract(&endpoint_client.address, || {
130
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender2, &nonce2)
131
+ });
132
+
133
+ // Verify each sender has its own independent lazy nonce
134
+ let retrieved_nonce1 = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender1);
135
+ let retrieved_nonce2 = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender2);
136
+
137
+ assert_eq!(retrieved_nonce1, nonce1);
138
+ assert_eq!(retrieved_nonce2, nonce2);
139
+
140
+ // Verify a third sender still has initial nonce of 0
141
+ let sender3 = BytesN::from_array(env, &[3u8; 32]);
142
+ let retrieved_nonce3 = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender3);
143
+ assert_eq!(retrieved_nonce3, 0);
144
+ }
145
+
146
+ #[test]
147
+ fn test_lazy_inbound_nonce_large_values() {
148
+ let test_setup = setup();
149
+ let env = &test_setup.env;
150
+ let endpoint_client = &test_setup.endpoint_client;
151
+
152
+ let receiver = Address::generate(env);
153
+ let src_eid = 2;
154
+ let sender = BytesN::from_array(env, &[1u8; 32]);
155
+
156
+ // Test with maximum u64 value
157
+ let max_nonce = u64::MAX;
158
+ env.as_contract(&endpoint_client.address, || {
159
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &max_nonce)
160
+ });
161
+
162
+ let retrieved_nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
163
+ assert_eq!(retrieved_nonce, max_nonce);
164
+
165
+ // Test with large but not maximum value
166
+ let large_nonce = u64::MAX - 1000;
167
+ env.as_contract(&endpoint_client.address, || {
168
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &large_nonce)
169
+ });
170
+
171
+ let retrieved_large_nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
172
+ assert_eq!(retrieved_large_nonce, large_nonce);
173
+ }
174
+
175
+ #[test]
176
+ fn test_lazy_inbound_nonce_incremental_updates() {
177
+ let test_setup = setup();
178
+ let env = &test_setup.env;
179
+ let endpoint_client = &test_setup.endpoint_client;
180
+
181
+ let receiver = Address::generate(env);
182
+ let src_eid = 2;
183
+ let sender = BytesN::from_array(env, &[1u8; 32]);
184
+
185
+ // Start with nonce 0
186
+ let initial_nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
187
+ assert_eq!(initial_nonce, 0);
188
+
189
+ // Incrementally update lazy nonce
190
+ for expected_nonce in 1..=10 {
191
+ env.as_contract(&endpoint_client.address, || {
192
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &expected_nonce)
193
+ });
194
+
195
+ let retrieved_nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
196
+ assert_eq!(retrieved_nonce, expected_nonce);
197
+ }
198
+ }
199
+
200
+ #[test]
201
+ fn test_lazy_inbound_nonce_overwrite() {
202
+ let test_setup = setup();
203
+ let env = &test_setup.env;
204
+ let endpoint_client = &test_setup.endpoint_client;
205
+
206
+ let receiver = Address::generate(env);
207
+ let src_eid = 2;
208
+ let sender = BytesN::from_array(env, &[1u8; 32]);
209
+
210
+ // Set initial nonce
211
+ let initial_nonce = 100;
212
+ env.as_contract(&endpoint_client.address, || {
213
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &initial_nonce)
214
+ });
215
+
216
+ let retrieved_initial = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
217
+ assert_eq!(retrieved_initial, initial_nonce);
218
+
219
+ // Overwrite with a different nonce
220
+ let new_nonce = 200;
221
+ env.as_contract(&endpoint_client.address, || {
222
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &new_nonce)
223
+ });
224
+
225
+ let retrieved_new = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
226
+ assert_eq!(retrieved_new, new_nonce);
227
+
228
+ // Overwrite with a smaller nonce
229
+ let smaller_nonce = 50;
230
+ env.as_contract(&endpoint_client.address, || {
231
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &smaller_nonce)
232
+ });
233
+
234
+ let retrieved_smaller = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
235
+ assert_eq!(retrieved_smaller, smaller_nonce);
236
+ }
237
+
238
+ #[test]
239
+ fn test_lazy_inbound_nonce_multiple_paths_independence() {
240
+ let test_setup = setup();
241
+ let env = &test_setup.env;
242
+ let endpoint_client = &test_setup.endpoint_client;
243
+
244
+ let receiver1 = Address::generate(env);
245
+ let receiver2 = Address::generate(env);
246
+ let src_eid1 = 2;
247
+ let src_eid2 = 3;
248
+ let sender1 = BytesN::from_array(env, &[1u8; 32]);
249
+ let sender2 = BytesN::from_array(env, &[2u8; 32]);
250
+
251
+ // Set nonces for different combinations
252
+ let nonce_r1_e1_s1 = 100;
253
+ let nonce_r1_e1_s2 = 200;
254
+ let nonce_r1_e2_s1 = 300;
255
+ let nonce_r2_e1_s1 = 400;
256
+
257
+ env.as_contract(&endpoint_client.address, || {
258
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid1, &sender1, &nonce_r1_e1_s1)
259
+ });
260
+ env.as_contract(&endpoint_client.address, || {
261
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid1, &sender2, &nonce_r1_e1_s2)
262
+ });
263
+ env.as_contract(&endpoint_client.address, || {
264
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver1, src_eid2, &sender1, &nonce_r1_e2_s1)
265
+ });
266
+ env.as_contract(&endpoint_client.address, || {
267
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver2, src_eid1, &sender1, &nonce_r2_e1_s1)
268
+ });
269
+
270
+ // Verify all paths are independent
271
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver1, &src_eid1, &sender1), nonce_r1_e1_s1);
272
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver1, &src_eid1, &sender2), nonce_r1_e1_s2);
273
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver1, &src_eid2, &sender1), nonce_r1_e2_s1);
274
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver2, &src_eid1, &sender1), nonce_r2_e1_s1);
275
+
276
+ // Verify unset paths still return 0
277
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver2, &src_eid1, &sender2), 0);
278
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver2, &src_eid2, &sender1), 0);
279
+ assert_eq!(endpoint_client.lazy_inbound_nonce(&receiver2, &src_eid2, &sender2), 0);
280
+ }
281
+
282
+ #[test]
283
+ fn test_lazy_inbound_nonce_zero_value() {
284
+ let test_setup = setup();
285
+ let env = &test_setup.env;
286
+ let endpoint_client = &test_setup.endpoint_client;
287
+
288
+ let receiver = Address::generate(env);
289
+ let src_eid = 2;
290
+ let sender = BytesN::from_array(env, &[1u8; 32]);
291
+
292
+ // Set lazy nonce to a non-zero value first
293
+ env.as_contract(&endpoint_client.address, || {
294
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &50)
295
+ });
296
+
297
+ let non_zero_nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
298
+ assert_eq!(non_zero_nonce, 50);
299
+
300
+ // Set lazy nonce back to 0
301
+ env.as_contract(&endpoint_client.address, || {
302
+ storage::EndpointStorage::set_lazy_inbound_nonce(env, &receiver, src_eid, &sender, &0)
303
+ });
304
+
305
+ let zero_nonce = endpoint_client.lazy_inbound_nonce(&receiver, &src_eid, &sender);
306
+ assert_eq!(zero_nonce, 0);
307
+ }