@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.9

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 (239) hide show
  1. package/.turbo/turbo-build.log +443 -302
  2. package/.turbo/turbo-lint.log +118 -96
  3. package/.turbo/turbo-test.log +853 -731
  4. package/Cargo.lock +120 -37
  5. package/Cargo.toml +8 -5
  6. package/contracts/common-macros/src/contract_impl.rs +44 -0
  7. package/contracts/common-macros/src/lib.rs +86 -40
  8. package/contracts/common-macros/src/ownable.rs +24 -32
  9. package/contracts/common-macros/src/storage.rs +95 -120
  10. package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
  11. package/contracts/common-macros/src/tests/mod.rs +9 -0
  12. package/contracts/common-macros/src/tests/ownable.rs +151 -0
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
  18. package/contracts/common-macros/src/tests/storage.rs +485 -0
  19. package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
  20. package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
  21. package/contracts/common-macros/src/ttl_configurable.rs +31 -14
  22. package/contracts/common-macros/src/utils.rs +27 -0
  23. package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
  24. package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
  25. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
  26. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
  27. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
  28. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
  29. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
  30. package/contracts/endpoint-v2/src/lib.rs +6 -5
  31. package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
  32. package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
  33. package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
  34. package/contracts/endpoint-v2/src/storage.rs +10 -7
  35. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
  36. package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
  37. package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
  38. package/contracts/endpoint-v2/src/util.rs +8 -2
  39. package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
  40. package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
  41. package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
  42. package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
  43. package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
  44. package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
  45. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
  46. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
  47. package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
  48. package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
  49. package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
  50. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
  51. package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
  52. package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
  53. package/contracts/message-libs/treasury/src/storage.rs +1 -2
  54. package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
  55. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
  56. package/contracts/message-libs/treasury/src/treasury.rs +18 -21
  57. package/contracts/message-libs/uln-302/Cargo.toml +1 -0
  58. package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
  59. package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
  60. package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
  61. package/contracts/message-libs/uln-302/src/lib.rs +5 -4
  62. package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
  63. package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
  64. package/contracts/message-libs/uln-302/src/storage.rs +1 -2
  65. package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
  66. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
  67. package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
  68. package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
  69. package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
  70. package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
  71. package/contracts/oapp-macros/Cargo.toml +2 -8
  72. package/contracts/oapp-macros/src/lib.rs +57 -311
  73. package/contracts/oapp-macros/src/oapp_core.rs +23 -32
  74. package/contracts/oapp-macros/src/oapp_full.rs +8 -2
  75. package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
  76. package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
  77. package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
  78. package/contracts/oapp-macros/src/util.rs +14 -10
  79. package/contracts/oapps/counter/Cargo.toml +2 -1
  80. package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
  81. package/contracts/oapps/counter/src/codec.rs +8 -9
  82. package/contracts/oapps/counter/src/counter.rs +156 -147
  83. package/contracts/oapps/counter/src/storage.rs +1 -2
  84. package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
  85. package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
  86. package/contracts/oapps/oapp/Cargo.toml +1 -0
  87. package/contracts/oapps/oapp/src/errors.rs +1 -1
  88. package/contracts/oapps/oapp/src/lib.rs +3 -0
  89. package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
  90. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
  91. package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
  92. package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
  93. package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
  94. package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
  95. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
  96. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
  97. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
  98. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
  99. package/contracts/oapps/oft/Cargo.toml +27 -0
  100. package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
  101. package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
  102. package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
  103. package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
  104. package/contracts/oapps/oft/src/codec/mod.rs +2 -0
  105. package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
  106. package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
  107. package/contracts/oapps/oft/src/constants.rs +5 -0
  108. package/contracts/oapps/oft/src/errors.rs +8 -0
  109. package/contracts/oapps/oft/src/events.rs +19 -0
  110. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
  111. package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
  112. package/contracts/oapps/oft/src/lib.rs +22 -0
  113. package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
  114. package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
  115. package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
  116. package/contracts/oapps/oft/src/oft.rs +320 -0
  117. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
  118. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
  119. package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
  120. package/contracts/oapps/oft/src/storage.rs +11 -0
  121. package/contracts/oapps/oft/src/tests/mod.rs +13 -0
  122. package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
  123. package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
  124. package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
  125. package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
  126. package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
  127. package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
  128. package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
  129. package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
  130. package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
  131. package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
  132. package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
  133. package/contracts/oapps/oft/src/types.rs +38 -0
  134. package/contracts/oapps/oft/src/utils.rs +67 -0
  135. package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
  136. package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
  137. package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
  138. package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
  139. package/contracts/utils/src/buffer_reader.rs +8 -9
  140. package/contracts/utils/src/buffer_writer.rs +11 -5
  141. package/contracts/utils/src/errors.rs +5 -5
  142. package/contracts/utils/src/ownable.rs +14 -6
  143. package/contracts/utils/src/testing_utils.rs +11 -1
  144. package/contracts/utils/src/tests/buffer_reader.rs +491 -730
  145. package/contracts/utils/src/tests/buffer_writer.rs +336 -148
  146. package/contracts/utils/src/tests/bytes_ext.rs +125 -40
  147. package/contracts/utils/src/tests/mod.rs +3 -0
  148. package/contracts/utils/src/tests/ownable.rs +379 -27
  149. package/contracts/utils/src/tests/test_helper.rs +47 -0
  150. package/contracts/utils/src/tests/testing_utils.rs +555 -0
  151. package/contracts/utils/src/tests/ttl.rs +421 -0
  152. package/contracts/utils/src/ttl.rs +29 -89
  153. package/contracts/workers/dvn/Cargo.toml +31 -0
  154. package/contracts/workers/dvn/src/auth.rs +66 -0
  155. package/contracts/workers/dvn/src/dvn.rs +143 -0
  156. package/contracts/workers/dvn/src/errors.rs +21 -0
  157. package/contracts/workers/dvn/src/events.rs +19 -0
  158. package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
  159. package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
  160. package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
  161. package/contracts/workers/dvn/src/lib.rs +24 -0
  162. package/contracts/workers/dvn/src/multisig.rs +127 -0
  163. package/contracts/workers/dvn/src/storage.rs +35 -0
  164. package/contracts/workers/dvn/src/tests/auth.rs +237 -0
  165. package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
  166. package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
  167. package/contracts/workers/dvn/src/tests/mod.rs +5 -0
  168. package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
  169. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
  170. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
  171. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
  172. package/contracts/workers/dvn/src/tests/setup.rs +109 -0
  173. package/contracts/workers/dvn/src/types.rs +26 -0
  174. package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
  175. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
  176. package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
  177. package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
  178. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
  179. package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
  180. package/contracts/workers/executor/Cargo.toml +10 -7
  181. package/contracts/workers/executor/src/errors.rs +8 -0
  182. package/contracts/workers/executor/src/events.rs +4 -7
  183. package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
  184. package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
  185. package/contracts/workers/executor/src/lib.rs +16 -7
  186. package/contracts/workers/executor/src/lz_executor.rs +308 -0
  187. package/contracts/workers/executor/src/storage.rs +24 -16
  188. package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
  189. package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
  190. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
  191. package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
  192. package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
  193. package/contracts/workers/executor-helper/Cargo.toml +29 -0
  194. package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
  195. package/contracts/workers/executor-helper/src/lib.rs +11 -0
  196. package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
  197. package/contracts/workers/worker/src/errors.rs +24 -0
  198. package/contracts/workers/worker/src/events.rs +62 -0
  199. package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
  200. package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
  201. package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
  202. package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
  203. package/contracts/workers/worker/src/lib.rs +14 -0
  204. package/contracts/workers/worker/src/storage.rs +63 -0
  205. package/contracts/workers/worker/src/worker.rs +459 -0
  206. package/package.json +3 -3
  207. package/sdk/dist/generated/bml.d.ts +88 -17
  208. package/sdk/dist/generated/bml.js +62 -16
  209. package/sdk/dist/generated/counter.d.ts +281 -102
  210. package/sdk/dist/generated/counter.js +93 -41
  211. package/sdk/dist/generated/endpoint.d.ts +128 -105
  212. package/sdk/dist/generated/endpoint.js +47 -45
  213. package/sdk/dist/generated/sml.d.ts +212 -69
  214. package/sdk/dist/generated/sml.js +103 -53
  215. package/sdk/dist/generated/uln302.d.ts +270 -173
  216. package/sdk/dist/generated/uln302.js +112 -64
  217. package/sdk/package.json +11 -11
  218. package/sdk/test/index.test.ts +147 -42
  219. package/sdk/test/suites/constants.ts +7 -3
  220. package/sdk/test/suites/deploy.ts +65 -42
  221. package/sdk/test/suites/localnet.ts +2 -2
  222. package/sdk/test/suites/scan.ts +28 -25
  223. package/sdk/test/utils.ts +199 -0
  224. package/sdk/tsconfig.json +93 -95
  225. package/tools/ts-bindings-gen/src/main.rs +2 -0
  226. package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
  227. package/contracts/common-macros/src/tests.rs +0 -287
  228. package/contracts/oapp-macros/tests/test_macros.rs +0 -522
  229. package/contracts/workers/executor/src/executor.rs +0 -347
  230. package/contracts/workers/executor/src/interfaces/types.rs +0 -51
  231. package/contracts/workers/worker-common/src/constants.rs +0 -17
  232. package/contracts/workers/worker-common/src/errors.rs +0 -6
  233. package/contracts/workers/worker-common/src/events.rs +0 -34
  234. package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
  235. package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
  236. package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
  237. package/contracts/workers/worker-common/src/lib.rs +0 -19
  238. package/contracts/workers/worker-common/src/storage.rs +0 -32
  239. package/contracts/workers/worker-common/src/worker_common.rs +0 -166
@@ -1,77 +1,162 @@
1
1
  use soroban_sdk::{Bytes, Env};
2
2
 
3
3
  use crate::bytes_ext::BytesExt;
4
+ use crate::tests::test_helper::assert_panics_contains;
5
+
6
+ // ============================================
7
+ // Helper functions
8
+ // ============================================
9
+
10
+ /// Helper to assert that `to_array::<N>()` panics with BytesExtError::LengthMismatch (1400)
11
+ fn assert_to_array_panics<const N: usize>(case: &str, raw: &[u8]) {
12
+ const EXPECTED: &str = "Error(Contract, #1400)";
13
+ assert_panics_contains(case, EXPECTED, || {
14
+ let env = Env::default();
15
+ let bytes = Bytes::from_slice(&env, raw);
16
+ let _arr: [u8; N] = bytes.to_array();
17
+ });
18
+ }
19
+
20
+ // ============================================
21
+ // Successful conversion tests
22
+ // ============================================
4
23
 
5
24
  #[test]
6
- fn test_to_array_exact_length() {
25
+ fn test_to_array_various_sizes() {
7
26
  let env = Env::default();
8
- let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
9
-
10
- let arr: [u8; 4] = bytes.to_array();
11
27
 
12
- assert_eq!(arr, [0x01, 0x02, 0x03, 0x04]);
13
- }
28
+ // Empty array
29
+ let bytes = Bytes::from_array(&env, &[]);
30
+ let arr: [u8; 0] = bytes.to_array();
31
+ let expected: [u8; 0] = [];
32
+ assert_eq!(arr, expected);
14
33
 
15
- #[test]
16
- fn test_to_array_single_byte() {
17
- let env = Env::default();
34
+ // Single byte
18
35
  let bytes = Bytes::from_array(&env, &[0xAB]);
36
+ assert_eq!(bytes.to_array::<1>(), [0xAB]);
19
37
 
20
- let arr: [u8; 1] = bytes.to_array();
38
+ // Two bytes
39
+ let bytes = Bytes::from_array(&env, &[0xAB, 0xCD]);
40
+ assert_eq!(bytes.to_array::<2>(), [0xAB, 0xCD]);
21
41
 
22
- assert_eq!(arr, [0xAB]);
23
- }
42
+ // Four bytes
43
+ let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04]);
44
+ assert_eq!(bytes.to_array::<4>(), [0x01, 0x02, 0x03, 0x04]);
24
45
 
25
- #[test]
26
- fn test_to_array_preserves_order() {
27
- let env = Env::default();
46
+ // Eight bytes - verify order preserved
28
47
  let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
29
-
30
- let arr: [u8; 8] = bytes.to_array();
31
-
32
- // Verify bytes are in correct order (big-endian preservation)
48
+ let arr = bytes.to_array::<8>();
33
49
  assert_eq!(arr[0], 0x01);
34
50
  assert_eq!(arr[7], 0x08);
51
+
52
+ // 32 bytes
53
+ let data: [u8; 32] = [0x42; 32];
54
+ let bytes = Bytes::from_array(&env, &data);
55
+ assert_eq!(bytes.to_array::<32>(), data);
56
+
57
+ // 64 bytes
58
+ let data: [u8; 64] = core::array::from_fn(|i| i as u8);
59
+ let bytes = Bytes::from_array(&env, &data);
60
+ assert_eq!(bytes.to_array::<64>(), data);
35
61
  }
36
62
 
37
63
  #[test]
38
- #[should_panic]
39
- fn test_to_array_length_mismatch_too_short() {
64
+ fn test_to_array_boundary_values() {
40
65
  let env = Env::default();
41
- // Bytes has 3 elements, but trying to convert to [u8; 4]
42
- let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03]);
43
66
 
44
- let _arr: [u8; 4] = bytes.to_array();
67
+ // All zeros
68
+ let data: [u8; 16] = [0x00; 16];
69
+ let bytes = Bytes::from_array(&env, &data);
70
+ let arr: [u8; 16] = bytes.to_array();
71
+ assert_eq!(arr, data);
72
+
73
+ // All ones
74
+ let data: [u8; 16] = [0xFF; 16];
75
+ let bytes = Bytes::from_array(&env, &data);
76
+ let arr: [u8; 16] = bytes.to_array();
77
+ assert_eq!(arr, data);
78
+
79
+ // Boundary byte values
80
+ let bytes = Bytes::from_array(&env, &[0x00, 0x7F, 0x80, 0xFF]);
81
+ let arr: [u8; 4] = bytes.to_array();
82
+ assert_eq!(arr[0], 0x00); // min
83
+ assert_eq!(arr[1], 0x7F); // max positive signed
84
+ assert_eq!(arr[2], 0x80); // min negative signed
85
+ assert_eq!(arr[3], 0xFF); // max
86
+
87
+ // Sequential values
88
+ let data: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
89
+ let bytes = Bytes::from_array(&env, &data);
90
+ let arr: [u8; 10] = bytes.to_array();
91
+ for i in 0..10 {
92
+ assert_eq!(arr[i], i as u8);
93
+ }
94
+ }
95
+
96
+ // ============================================
97
+ // Length mismatch tests (error conditions)
98
+ // ============================================
99
+
100
+ #[test]
101
+ fn test_to_array_length_mismatch_panics_table() {
102
+ // Bytes too short
103
+ assert_to_array_panics::<4>("3 bytes to [u8; 4]", &[0x01, 0x02, 0x03]);
104
+ // Bytes too long
105
+ assert_to_array_panics::<4>("5 bytes to [u8; 4]", &[0x01, 0x02, 0x03, 0x04, 0x05]);
106
+ // Empty to non-empty
107
+ assert_to_array_panics::<4>("0 bytes to [u8; 4]", &[]);
108
+ // Off-by-one short
109
+ assert_to_array_panics::<8>("7 bytes to [u8; 8]", &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]);
110
+ // Off-by-one long
111
+ assert_to_array_panics::<8>("9 bytes to [u8; 8]", &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]);
112
+ // Significantly wrong size
113
+ assert_to_array_panics::<32>("4 bytes to [u8; 32]", &[0x01, 0x02, 0x03, 0x04]);
45
114
  }
46
115
 
47
116
  #[test]
48
- #[should_panic]
49
- fn test_to_array_length_mismatch_too_long() {
117
+ fn test_to_array_large_sizes() {
50
118
  let env = Env::default();
51
- // Bytes has 5 elements, but trying to convert to [u8; 4]
52
- let bytes = Bytes::from_array(&env, &[0x01, 0x02, 0x03, 0x04, 0x05]);
53
119
 
54
- let _arr: [u8; 4] = bytes.to_array();
120
+ // Test with 128 bytes
121
+ let data: [u8; 128] = core::array::from_fn(|i| (i % 256) as u8);
122
+ let bytes = Bytes::from_array(&env, &data);
123
+ assert_eq!(bytes.to_array::<128>(), data);
124
+
125
+ // Test with 256 bytes
126
+ let data: [u8; 256] = core::array::from_fn(|i| (i % 256) as u8);
127
+ let bytes = Bytes::from_array(&env, &data);
128
+ assert_eq!(bytes.to_array::<256>(), data);
55
129
  }
56
130
 
57
131
  #[test]
58
- #[should_panic]
59
- fn test_to_array_empty_to_non_empty() {
132
+ fn test_to_array_very_large_size() {
60
133
  let env = Env::default();
61
- let bytes = Bytes::from_array(&env, &[]);
62
134
 
63
- // Trying to convert empty bytes to non-empty array should panic
64
- let _arr: [u8; 4] = bytes.to_array();
135
+ // Test with 512 bytes to ensure it works beyond 256
136
+ let data: [u8; 512] = core::array::from_fn(|i| (i % 256) as u8);
137
+ let bytes = Bytes::from_array(&env, &data);
138
+ let arr = bytes.to_array::<512>();
139
+
140
+ // Verify first and last elements
141
+ assert_eq!(arr[0], 0);
142
+ assert_eq!(arr[255], 255);
143
+ assert_eq!(arr[256], 0);
144
+ assert_eq!(arr[511], 255);
145
+
146
+ // Verify full array matches
147
+ assert_eq!(arr, data);
65
148
  }
66
149
 
67
150
  #[test]
68
- fn test_to_array_empty_to_empty() {
151
+ fn test_to_array_preserves_all_values() {
69
152
  let env = Env::default();
70
- let bytes = Bytes::from_array(&env, &[]);
71
153
 
72
- // Converting empty bytes to empty array should work
73
- let arr: [u8; 0] = bytes.to_array();
74
- let expected: [u8; 0] = [];
154
+ // Test that all byte values (0-255) are preserved correctly
155
+ let data: [u8; 256] = core::array::from_fn(|i| i as u8);
156
+ let bytes = Bytes::from_array(&env, &data);
157
+ let arr: [u8; 256] = bytes.to_array();
75
158
 
76
- assert_eq!(arr, expected);
159
+ for i in 0..256 {
160
+ assert_eq!(arr[i], i as u8, "Mismatch at index {}", i);
161
+ }
77
162
  }
@@ -2,3 +2,6 @@ mod buffer_reader;
2
2
  mod buffer_writer;
3
3
  mod bytes_ext;
4
4
  mod ownable;
5
+ mod test_helper;
6
+ mod testing_utils;
7
+ mod ttl;
@@ -1,6 +1,9 @@
1
1
  use crate::{
2
2
  errors::OwnableError,
3
- ownable::{self, DefaultOwnable, DefaultOwnableStorage, Ownable, OwnershipTransferred},
3
+ ownable::{
4
+ self, DefaultOwnable, DefaultOwnableStorage, Ownable, OwnableInitializer, OwnershipRenounced,
5
+ OwnershipTransferred,
6
+ },
4
7
  testing_utils::assert_event,
5
8
  };
6
9
  use soroban_sdk::{
@@ -23,8 +26,8 @@ impl Contract {
23
26
  1
24
27
  }
25
28
 
26
- pub fn remove_owner_no_auth(env: &Env) {
27
- DefaultOwnableStorage::remove_owner(env);
29
+ pub fn enforce_and_return_owner(env: &Env) -> Address {
30
+ ownable::enforce_owner_auth::<Self>(env)
28
31
  }
29
32
 
30
33
  pub fn init_owner(env: &Env, owner: &Address) {
@@ -33,6 +36,10 @@ impl Contract {
33
36
  }
34
37
  DefaultOwnableStorage::set_owner(env, owner);
35
38
  }
39
+
40
+ pub fn remove_owner(env: &Env) {
41
+ DefaultOwnableStorage::remove_owner(env);
42
+ }
36
43
  }
37
44
 
38
45
  #[contractimpl]
@@ -50,14 +57,32 @@ impl Ownable for Contract {
50
57
  }
51
58
  }
52
59
 
60
+ /// Contract that does not implement Ownable trait - for testing raw init_owner
61
+ #[contract]
62
+ pub struct NonOwnableContract;
63
+
64
+ #[contractimpl]
65
+ impl NonOwnableContract {
66
+ pub fn init(env: &Env, owner: &Address) {
67
+ DefaultOwnable::init_owner(env, owner);
68
+ }
69
+
70
+ pub fn owner(env: &Env) -> Option<Address> {
71
+ DefaultOwnable::owner(env)
72
+ }
73
+ }
74
+
75
+ // ============================================
76
+ // auth: Owner authentication tests
77
+ // ============================================
78
+
53
79
  #[test]
54
- fn test_owner_can_call() {
80
+ fn auth_owner_can_call() {
55
81
  let env = Env::default();
56
-
57
82
  let owner = Address::generate(&env);
58
83
 
59
84
  let contract = env.register(Contract, (&owner,));
60
- let contract_client = ContractClient::new(&env, &contract);
85
+ let client = ContractClient::new(&env, &contract);
61
86
 
62
87
  env.mock_auths(&[MockAuth {
63
88
  address: &owner,
@@ -68,32 +93,58 @@ fn test_owner_can_call() {
68
93
  sub_invokes: &[],
69
94
  },
70
95
  }]);
71
- contract_client.require_owner_auth();
96
+ client.require_owner_auth();
72
97
  }
73
98
 
74
99
  #[test]
75
100
  #[should_panic(expected = "Error(Auth, InvalidAction)")]
76
- fn test_non_owner_cannot_call() {
101
+ fn auth_non_owner_cannot_call() {
77
102
  let env = Env::default();
78
-
79
103
  let owner = Address::generate(&env);
80
104
  let contract = env.register(Contract, (&owner,));
81
- let contract_client = ContractClient::new(&env, &contract);
105
+ let client = ContractClient::new(&env, &contract);
82
106
 
83
- contract_client.require_owner_auth();
107
+ // Try to call without auth should fail
108
+ client.require_owner_auth();
84
109
  }
85
110
 
86
111
  #[test]
87
- fn test_transfer_ownership() {
112
+ #[should_panic(expected = "Error(Contract, #1301)")]
113
+ fn auth_require_owner_when_no_owner_set() {
88
114
  let env = Env::default();
115
+ let owner = Address::generate(&env);
116
+
117
+ let contract = env.register(Contract, (&owner,));
118
+ let client = ContractClient::new(&env, &contract);
119
+ client.remove_owner();
120
+
121
+ env.mock_auths(&[MockAuth {
122
+ address: &owner,
123
+ invoke: &MockAuthInvoke {
124
+ contract: &contract,
125
+ args: ().into_val(&env),
126
+ fn_name: "require_owner_auth",
127
+ sub_invokes: &[],
128
+ },
129
+ }]);
130
+ client.require_owner_auth();
131
+ }
132
+
133
+ // ============================================
134
+ // transfer: Transfer ownership tests
135
+ // ============================================
89
136
 
137
+ #[test]
138
+ fn transfer_ownership_with_event() {
139
+ let env = Env::default();
90
140
  let owner = Address::generate(&env);
91
141
  let new_owner = Address::generate(&env);
92
142
 
93
143
  let contract = env.register(Contract, (&owner,));
94
- let contract_client = ContractClient::new(&env, &contract);
144
+ let client = ContractClient::new(&env, &contract);
145
+
146
+ assert_eq!(client.owner(), Some(owner.clone()));
95
147
 
96
- assert_eq!(contract_client.owner(), Some(owner.clone()));
97
148
  env.mock_auths(&[MockAuth {
98
149
  address: &owner,
99
150
  invoke: &MockAuthInvoke {
@@ -103,47 +154,348 @@ fn test_transfer_ownership() {
103
154
  sub_invokes: &[],
104
155
  },
105
156
  }]);
106
- contract_client.transfer_ownership(&new_owner);
157
+ client.transfer_ownership(&new_owner);
107
158
 
108
159
  assert_event(&env, &contract, OwnershipTransferred { old_owner: owner, new_owner: new_owner.clone() });
160
+ assert_eq!(client.owner(), Some(new_owner));
161
+ }
162
+
163
+ #[test]
164
+ fn transfer_ownership_to_same_owner() {
165
+ let env = Env::default();
166
+ let owner = Address::generate(&env);
167
+
168
+ let contract = env.register(Contract, (&owner,));
169
+ let client = ContractClient::new(&env, &contract);
170
+
171
+ assert_eq!(client.owner(), Some(owner.clone()));
172
+
173
+ env.mock_auths(&[MockAuth {
174
+ address: &owner,
175
+ invoke: &MockAuthInvoke {
176
+ contract: &contract,
177
+ args: (&owner,).into_val(&env),
178
+ fn_name: "transfer_ownership",
179
+ sub_invokes: &[],
180
+ },
181
+ }]);
182
+ client.transfer_ownership(&owner);
183
+
184
+ // Should still emit event and update (even if same owner)
185
+ assert_event(&env, &contract, OwnershipTransferred { old_owner: owner.clone(), new_owner: owner.clone() });
186
+ assert_eq!(client.owner(), Some(owner));
187
+ }
188
+
189
+ #[test]
190
+ #[should_panic(expected = "Error(Auth, InvalidAction)")]
191
+ fn transfer_ownership_requires_auth() {
192
+ let env = Env::default();
193
+ let owner = Address::generate(&env);
194
+ let new_owner = Address::generate(&env);
195
+
196
+ let contract = env.register(Contract, (&owner,));
197
+ let client = ContractClient::new(&env, &contract);
109
198
 
110
- // assert owner
111
- assert_eq!(contract_client.owner(), Some(new_owner.clone()));
199
+ // Try to transfer without auth should fail
200
+ client.transfer_ownership(&new_owner);
112
201
  }
113
202
 
114
203
  #[test]
115
- fn test_call_no_owner_set() {
204
+ #[should_panic(expected = "Error(Contract, #1301)")]
205
+ fn transfer_after_renounce_fails() {
116
206
  let env = Env::default();
207
+ let owner = Address::generate(&env);
208
+ let new_owner = Address::generate(&env);
209
+
210
+ let contract = env.register(Contract, (&owner,));
211
+ let client = ContractClient::new(&env, &contract);
212
+
213
+ // Renounce ownership
214
+ env.mock_auths(&[MockAuth {
215
+ address: &owner,
216
+ invoke: &MockAuthInvoke {
217
+ contract: &contract,
218
+ args: ().into_val(&env),
219
+ fn_name: "renounce_ownership",
220
+ sub_invokes: &[],
221
+ },
222
+ }]);
223
+ client.renounce_ownership();
117
224
 
225
+ // Try to transfer after renounce - should fail with OwnerNotSet
226
+ env.mock_auths(&[MockAuth {
227
+ address: &owner,
228
+ invoke: &MockAuthInvoke {
229
+ contract: &contract,
230
+ args: (&new_owner,).into_val(&env),
231
+ fn_name: "transfer_ownership",
232
+ sub_invokes: &[],
233
+ },
234
+ }]);
235
+ client.transfer_ownership(&new_owner);
236
+ }
237
+
238
+ // ============================================
239
+ // renounce: Renounce ownership tests
240
+ // ============================================
241
+
242
+ #[test]
243
+ fn renounce_ownership_with_event() {
244
+ let env = Env::default();
118
245
  let owner = Address::generate(&env);
119
246
 
120
247
  let contract = env.register(Contract, (&owner,));
121
- let contract_client = ContractClient::new(&env, &contract);
122
- contract_client.remove_owner_no_auth();
248
+ let client = ContractClient::new(&env, &contract);
249
+
250
+ assert_eq!(client.owner(), Some(owner.clone()));
123
251
 
124
252
  env.mock_auths(&[MockAuth {
125
253
  address: &owner,
126
254
  invoke: &MockAuthInvoke {
127
255
  contract: &contract,
128
256
  args: ().into_val(&env),
129
- fn_name: "require_owner_auth",
257
+ fn_name: "renounce_ownership",
258
+ sub_invokes: &[],
259
+ },
260
+ }]);
261
+ client.renounce_ownership();
262
+
263
+ assert_event(&env, &contract, OwnershipRenounced { old_owner: owner });
264
+ assert_eq!(client.owner(), None);
265
+ }
266
+
267
+ #[test]
268
+ #[should_panic(expected = "Error(Auth, InvalidAction)")]
269
+ fn renounce_ownership_requires_auth() {
270
+ let env = Env::default();
271
+ let owner = Address::generate(&env);
272
+
273
+ let contract = env.register(Contract, (&owner,));
274
+ let client = ContractClient::new(&env, &contract);
275
+
276
+ // Try to renounce without auth should fail
277
+ client.renounce_ownership();
278
+ }
279
+
280
+ #[test]
281
+ #[should_panic(expected = "Error(Contract, #1301)")]
282
+ fn renounce_after_renounce_fails() {
283
+ let env = Env::default();
284
+ let owner = Address::generate(&env);
285
+
286
+ let contract = env.register(Contract, (&owner,));
287
+ let client = ContractClient::new(&env, &contract);
288
+
289
+ // Renounce ownership
290
+ env.mock_auths(&[MockAuth {
291
+ address: &owner,
292
+ invoke: &MockAuthInvoke {
293
+ contract: &contract,
294
+ args: ().into_val(&env),
295
+ fn_name: "renounce_ownership",
296
+ sub_invokes: &[],
297
+ },
298
+ }]);
299
+ client.renounce_ownership();
300
+
301
+ // Try to renounce again - should fail with OwnerNotSet
302
+ env.mock_auths(&[MockAuth {
303
+ address: &owner,
304
+ invoke: &MockAuthInvoke {
305
+ contract: &contract,
306
+ args: ().into_val(&env),
307
+ fn_name: "renounce_ownership",
130
308
  sub_invokes: &[],
131
309
  },
132
310
  }]);
133
- let result = contract_client.try_require_owner_auth();
134
- assert_eq!(result.err().unwrap().ok().unwrap(), OwnableError::OwnerNotSet.into());
311
+ client.renounce_ownership();
312
+ }
313
+
314
+ // ============================================
315
+ // chain: Ownership chain tests
316
+ // ============================================
317
+
318
+ #[test]
319
+ fn chain_new_owner_can_transfer() {
320
+ let env = Env::default();
321
+ let owner = Address::generate(&env);
322
+ let new_owner = Address::generate(&env);
323
+ let third_owner = Address::generate(&env);
324
+
325
+ let contract = env.register(Contract, (&owner,));
326
+ let client = ContractClient::new(&env, &contract);
327
+
328
+ // Transfer to new_owner
329
+ env.mock_auths(&[MockAuth {
330
+ address: &owner,
331
+ invoke: &MockAuthInvoke {
332
+ contract: &contract,
333
+ args: (&new_owner,).into_val(&env),
334
+ fn_name: "transfer_ownership",
335
+ sub_invokes: &[],
336
+ },
337
+ }]);
338
+ client.transfer_ownership(&new_owner);
339
+
340
+ // new_owner can now transfer to third_owner
341
+ env.mock_auths(&[MockAuth {
342
+ address: &new_owner,
343
+ invoke: &MockAuthInvoke {
344
+ contract: &contract,
345
+ args: (&third_owner,).into_val(&env),
346
+ fn_name: "transfer_ownership",
347
+ sub_invokes: &[],
348
+ },
349
+ }]);
350
+ client.transfer_ownership(&third_owner);
351
+
352
+ assert_eq!(client.owner(), Some(third_owner));
353
+ }
354
+
355
+ #[test]
356
+ #[should_panic(expected = "Error(Auth, InvalidAction)")]
357
+ fn chain_old_owner_cannot_transfer_after_transfer() {
358
+ let env = Env::default();
359
+ let owner = Address::generate(&env);
360
+ let new_owner = Address::generate(&env);
361
+ let third_owner = Address::generate(&env);
362
+
363
+ let contract = env.register(Contract, (&owner,));
364
+ let client = ContractClient::new(&env, &contract);
365
+
366
+ // Transfer to new_owner
367
+ env.mock_auths(&[MockAuth {
368
+ address: &owner,
369
+ invoke: &MockAuthInvoke {
370
+ contract: &contract,
371
+ args: (&new_owner,).into_val(&env),
372
+ fn_name: "transfer_ownership",
373
+ sub_invokes: &[],
374
+ },
375
+ }]);
376
+ client.transfer_ownership(&new_owner);
377
+
378
+ // Old owner tries to transfer again - should fail
379
+ env.mock_auths(&[MockAuth {
380
+ address: &owner,
381
+ invoke: &MockAuthInvoke {
382
+ contract: &contract,
383
+ args: (&third_owner,).into_val(&env),
384
+ fn_name: "transfer_ownership",
385
+ sub_invokes: &[],
386
+ },
387
+ }]);
388
+ client.transfer_ownership(&third_owner);
389
+ }
390
+
391
+ // ============================================
392
+ // init: DefaultOwnable::init_owner tests
393
+ // ============================================
394
+
395
+ #[test]
396
+ fn init_owner_success() {
397
+ let env = Env::default();
398
+ let owner = Address::generate(&env);
399
+ let contract = env.register(NonOwnableContract, ());
400
+ let client = NonOwnableContractClient::new(&env, &contract);
401
+
402
+ assert_eq!(client.owner(), None);
403
+ client.init(&owner);
404
+ assert_eq!(client.owner(), Some(owner));
135
405
  }
136
406
 
137
407
  #[test]
138
- fn test_set_owner_when_already_set() {
408
+ #[should_panic(expected = "Error(Contract, #1300)")]
409
+ fn init_owner_already_set_fails() {
139
410
  let env = Env::default();
411
+ let owner = Address::generate(&env);
412
+ let new_owner = Address::generate(&env);
413
+ let contract = env.register(NonOwnableContract, ());
414
+ let client = NonOwnableContractClient::new(&env, &contract);
415
+
416
+ client.init(&owner);
417
+ client.init(&new_owner);
418
+ }
140
419
 
420
+ #[test]
421
+ #[should_panic(expected = "Error(Contract, #1300)")]
422
+ fn init_owner_when_already_set_fails() {
423
+ let env = Env::default();
141
424
  let owner = Address::generate(&env);
142
425
  let new_owner = Address::generate(&env);
143
426
 
144
427
  let contract = env.register(Contract, (&owner,));
145
- let contract_client = ContractClient::new(&env, &contract);
428
+ let client = ContractClient::new(&env, &contract);
429
+
430
+ client.init_owner(&new_owner);
431
+ }
432
+
433
+ // ============================================
434
+ // enforce: enforce_owner_auth tests
435
+ // ============================================
436
+
437
+ #[test]
438
+ fn enforce_owner_auth_returns_owner() {
439
+ let env = Env::default();
440
+ let owner = Address::generate(&env);
441
+ let contract = env.register(Contract, (&owner,));
442
+ let client = ContractClient::new(&env, &contract);
443
+
444
+ env.mock_auths(&[MockAuth {
445
+ address: &owner,
446
+ invoke: &MockAuthInvoke {
447
+ contract: &contract,
448
+ args: ().into_val(&env),
449
+ fn_name: "enforce_and_return_owner",
450
+ sub_invokes: &[],
451
+ },
452
+ }]);
453
+
454
+ let returned_owner = client.enforce_and_return_owner();
455
+ assert_eq!(returned_owner, owner);
456
+ }
457
+
458
+ #[test]
459
+ #[should_panic(expected = "Error(Contract, #1301)")]
460
+ fn enforce_owner_auth_no_owner_set_fails() {
461
+ let env = Env::default();
462
+ let owner = Address::generate(&env);
463
+ let contract = env.register(Contract, (&owner,));
464
+ let client = ContractClient::new(&env, &contract);
465
+
466
+ client.remove_owner();
467
+
468
+ env.mock_auths(&[MockAuth {
469
+ address: &owner,
470
+ invoke: &MockAuthInvoke {
471
+ contract: &contract,
472
+ args: ().into_val(&env),
473
+ fn_name: "enforce_and_return_owner",
474
+ sub_invokes: &[],
475
+ },
476
+ }]);
477
+
478
+ client.enforce_and_return_owner();
479
+ }
480
+
481
+ #[test]
482
+ #[should_panic(expected = "Error(Auth, InvalidAction)")]
483
+ fn enforce_owner_auth_wrong_address_fails() {
484
+ let env = Env::default();
485
+ let owner = Address::generate(&env);
486
+ let wrong_address = Address::generate(&env);
487
+ let contract = env.register(Contract, (&owner,));
488
+ let client = ContractClient::new(&env, &contract);
489
+
490
+ env.mock_auths(&[MockAuth {
491
+ address: &wrong_address,
492
+ invoke: &MockAuthInvoke {
493
+ contract: &contract,
494
+ args: ().into_val(&env),
495
+ fn_name: "enforce_and_return_owner",
496
+ sub_invokes: &[],
497
+ },
498
+ }]);
146
499
 
147
- let result = contract_client.try_init_owner(&new_owner);
148
- assert_eq!(result.err().unwrap().ok().unwrap(), OwnableError::OwnerAlreadySet.into());
500
+ client.enforce_and_return_owner();
149
501
  }