@layerzerolabs/protocol-stellar-v2 0.2.19 → 0.2.21

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 (249) hide show
  1. package/.turbo/turbo-build.log +795 -791
  2. package/.turbo/turbo-lint.log +325 -155
  3. package/.turbo/turbo-test.log +1398 -1277
  4. package/Cargo.lock +122 -111
  5. package/Cargo.toml +32 -16
  6. package/contracts/common-macros/Cargo.toml +7 -7
  7. package/contracts/common-macros/src/auth.rs +18 -37
  8. package/contracts/common-macros/src/contract_ttl.rs +18 -7
  9. package/contracts/common-macros/src/lib.rs +31 -14
  10. package/contracts/common-macros/src/lz_contract.rs +38 -7
  11. package/contracts/common-macros/src/storage.rs +251 -292
  12. package/contracts/common-macros/src/tests/contract_ttl.rs +1 -1
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +6 -12
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +12 -17
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap +2 -1
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +2 -7
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +20 -14
  18. package/contracts/common-macros/src/tests/upgradeable.rs +26 -4
  19. package/contracts/common-macros/src/ttl_configurable.rs +2 -10
  20. package/contracts/common-macros/src/ttl_extendable.rs +2 -10
  21. package/contracts/common-macros/src/upgradeable.rs +61 -26
  22. package/contracts/common-macros/src/utils.rs +0 -9
  23. package/contracts/endpoint-v2/src/lib.rs +3 -2
  24. package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +2 -2
  25. package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +3 -3
  26. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +4 -4
  27. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +17 -5
  28. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
  29. package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +2 -2
  30. package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +2 -2
  31. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +6 -6
  32. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +67 -37
  33. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +5 -5
  34. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +44 -54
  35. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +7 -7
  36. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +8 -8
  37. package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +3 -3
  38. package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +4 -4
  39. package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +3 -3
  40. package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +2 -2
  41. package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +3 -3
  42. package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +2 -2
  43. package/contracts/layerzero-views/Cargo.toml +0 -1
  44. package/contracts/layerzero-views/src/layerzero_view.rs +1 -13
  45. package/contracts/macro-integration-tests/Cargo.toml +5 -15
  46. package/contracts/macro-integration-tests/tests/runtime/oapp/mod.rs +48 -0
  47. package/contracts/macro-integration-tests/tests/runtime/oapp/oapp_core.rs +170 -0
  48. package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +154 -0
  49. package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +338 -0
  50. package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +435 -0
  51. package/contracts/macro-integration-tests/tests/runtime.rs +1 -0
  52. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.rs +8 -0
  53. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.stderr +5 -0
  54. package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.rs +8 -0
  55. package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.stderr +71 -0
  56. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.rs +10 -0
  57. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.stderr +5 -0
  58. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.rs +8 -0
  59. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.stderr +5 -0
  60. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.rs +8 -0
  61. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.stderr +5 -0
  62. package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_all.rs +38 -0
  63. package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_single_trait.rs +96 -0
  64. package/contracts/macro-integration-tests/tests/ui/oapp/pass/minimal_contract.rs +64 -0
  65. package/contracts/macro-integration-tests/tests/ui/oapp/pass/struct_with_fields.rs +46 -0
  66. package/contracts/macro-integration-tests/tests/ui/ownable/fail/only_auth_missing_env.stderr +8 -0
  67. package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +1 -1
  68. package/contracts/macro-integration-tests/tests/ui/ownable/pass/only_auth_env_param_variants.rs +1 -1
  69. package/contracts/macro-integration-tests/tests/ui_oapp.rs +11 -0
  70. package/contracts/message-libs/message-lib-common/Cargo.toml +0 -1
  71. package/contracts/message-libs/message-lib-common/src/errors.rs +1 -1
  72. package/contracts/message-libs/treasury/Cargo.toml +0 -2
  73. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +2 -2
  74. package/contracts/message-libs/uln-302/src/events.rs +4 -0
  75. package/contracts/message-libs/uln-302/src/send_uln.rs +22 -6
  76. package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +2 -2
  77. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +2 -2
  78. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +2 -2
  79. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +2 -2
  80. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +2 -2
  81. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +21 -67
  82. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +2 -2
  83. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +2 -2
  84. package/contracts/oapps/counter/Cargo.toml +5 -6
  85. package/contracts/oapps/counter/integration_tests/setup_uln.rs +1 -1
  86. package/contracts/oapps/counter/integration_tests/utils.rs +19 -12
  87. package/contracts/oapps/oapp/src/errors.rs +1 -1
  88. package/contracts/oapps/oapp/src/interfaces/mod.rs +3 -0
  89. package/contracts/oapps/oapp/src/interfaces/oapp_msg_inspector.rs +47 -0
  90. package/contracts/oapps/oapp/src/lib.rs +1 -0
  91. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +4 -4
  92. package/contracts/oapps/oapp/src/oapp_core.rs +5 -5
  93. package/contracts/oapps/oapp/src/oapp_options_type3.rs +12 -4
  94. package/contracts/oapps/oapp/src/oapp_receiver.rs +14 -9
  95. package/contracts/oapps/oapp/src/tests/mod.rs +4 -4
  96. package/contracts/oapps/oapp/src/tests/oapp_core.rs +223 -0
  97. package/contracts/oapps/oapp/src/tests/oapp_options_type3.rs +240 -0
  98. package/contracts/oapps/oapp/src/tests/oapp_receiver.rs +381 -0
  99. package/contracts/oapps/oapp/src/tests/oapp_sender.rs +569 -0
  100. package/contracts/oapps/oapp-macros/Cargo.toml +8 -4
  101. package/contracts/oapps/oapp-macros/src/generators.rs +9 -34
  102. package/contracts/oapps/oapp-macros/src/lib.rs +3 -0
  103. package/contracts/oapps/oapp-macros/src/tests/mod.rs +2 -0
  104. package/contracts/oapps/oapp-macros/src/tests/oapp.rs +88 -0
  105. package/contracts/oapps/oapp-macros/src/tests/parse_custom_impls.rs +86 -0
  106. package/contracts/oapps/oapp-macros/src/tests/snapshots/oapp_macros__tests__oapp__snapshot_generate_oapp.snap +103 -0
  107. package/contracts/oapps/oft/integration-tests/utils.rs +28 -8
  108. package/contracts/oapps/oft/src/extensions/oft_fee.rs +153 -75
  109. package/contracts/oapps/oft/src/extensions/pausable.rs +61 -12
  110. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +198 -134
  111. package/contracts/oapps/oft/src/oft.rs +45 -50
  112. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -1
  113. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +4 -26
  114. package/contracts/oapps/oft-core/Cargo.toml +1 -4
  115. package/contracts/oapps/oft-core/integration-tests/setup.rs +3 -3
  116. package/contracts/oapps/oft-core/integration-tests/utils.rs +21 -3
  117. package/contracts/oapps/oft-core/src/errors.rs +3 -2
  118. package/contracts/oapps/oft-core/src/events.rs +6 -0
  119. package/contracts/oapps/oft-core/src/lib.rs +1 -1
  120. package/contracts/oapps/oft-core/src/oft_core.rs +341 -246
  121. package/contracts/oapps/oft-core/src/storage.rs +7 -3
  122. package/contracts/oapps/oft-core/src/tests/mod.rs +1 -0
  123. package/contracts/oapps/oft-core/src/tests/test_decimals.rs +37 -2
  124. package/contracts/oapps/oft-core/src/tests/test_lz_receive.rs +2 -2
  125. package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +323 -0
  126. package/contracts/oapps/oft-core/src/tests/test_send.rs +2 -2
  127. package/contracts/oapps/oft-core/src/tests/test_utils.rs +61 -16
  128. package/contracts/upgrader/src/lib.rs +30 -57
  129. package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract1.wasm +0 -0
  130. package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract2.wasm +0 -0
  131. package/contracts/upgrader/src/tests/test_upgrader.rs +44 -35
  132. package/contracts/utils/Cargo.toml +0 -1
  133. package/contracts/utils/src/buffer_reader.rs +1 -0
  134. package/contracts/utils/src/errors.rs +4 -2
  135. package/contracts/utils/src/multisig.rs +17 -8
  136. package/contracts/utils/src/ownable.rs +6 -6
  137. package/contracts/utils/src/testing_utils.rs +124 -54
  138. package/contracts/utils/src/tests/multisig.rs +12 -12
  139. package/contracts/utils/src/tests/ownable.rs +6 -6
  140. package/contracts/utils/src/tests/testing_utils.rs +50 -167
  141. package/contracts/utils/src/tests/ttl_configurable.rs +5 -5
  142. package/contracts/utils/src/tests/upgradeable.rs +372 -175
  143. package/contracts/utils/src/ttl_configurable.rs +13 -7
  144. package/contracts/utils/src/upgradeable.rs +48 -23
  145. package/contracts/workers/dvn/Cargo.toml +6 -6
  146. package/contracts/workers/dvn/src/auth.rs +12 -42
  147. package/contracts/workers/dvn/src/dvn.rs +15 -40
  148. package/contracts/workers/dvn/src/errors.rs +0 -1
  149. package/contracts/workers/dvn/src/interfaces/dvn.rs +35 -0
  150. package/contracts/workers/dvn/src/lib.rs +4 -3
  151. package/contracts/workers/dvn/src/tests/auth.rs +1 -1
  152. package/contracts/workers/dvn/src/tests/dvn.rs +19 -15
  153. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +2 -4
  154. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +1 -3
  155. package/contracts/workers/dvn/src/tests/setup.rs +5 -9
  156. package/contracts/workers/dvn-fee-lib/Cargo.toml +2 -2
  157. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +38 -22
  158. package/contracts/workers/dvn-fee-lib/src/lib.rs +12 -2
  159. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +17 -16
  160. package/contracts/workers/executor/Cargo.toml +4 -0
  161. package/contracts/workers/executor/src/executor.rs +15 -36
  162. package/contracts/workers/executor/src/lib.rs +2 -2
  163. package/contracts/workers/executor/src/tests/auth.rs +394 -0
  164. package/contracts/workers/executor/src/tests/executor.rs +410 -0
  165. package/contracts/workers/executor/src/tests/mod.rs +3 -0
  166. package/contracts/workers/executor/src/tests/setup.rs +250 -0
  167. package/contracts/workers/executor-fee-lib/Cargo.toml +7 -1
  168. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +62 -15
  169. package/contracts/workers/executor-fee-lib/src/executor_option.rs +28 -1
  170. package/contracts/workers/executor-fee-lib/src/lib.rs +11 -2
  171. package/contracts/workers/executor-fee-lib/src/tests/executor_fee_lib.rs +701 -0
  172. package/contracts/workers/executor-fee-lib/src/tests/executor_option.rs +370 -0
  173. package/contracts/workers/executor-fee-lib/src/tests/mod.rs +4 -0
  174. package/contracts/workers/executor-fee-lib/src/tests/setup.rs +60 -0
  175. package/contracts/workers/executor-helper/Cargo.toml +0 -1
  176. package/contracts/workers/executor-helper/src/lib.rs +3 -0
  177. package/contracts/workers/executor-helper/src/tests/executor_helper.rs +184 -0
  178. package/contracts/workers/executor-helper/src/tests/mod.rs +2 -0
  179. package/contracts/workers/executor-helper/src/tests/setup.rs +366 -0
  180. package/contracts/workers/fee-lib-interfaces/Cargo.toml +14 -0
  181. package/contracts/workers/{worker/src/interfaces/mod.rs → fee-lib-interfaces/src/lib.rs} +4 -3
  182. package/contracts/workers/price-feed/Cargo.toml +7 -1
  183. package/contracts/workers/price-feed/src/events.rs +1 -1
  184. package/contracts/workers/price-feed/src/lib.rs +12 -4
  185. package/contracts/workers/price-feed/src/price_feed.rs +5 -21
  186. package/contracts/workers/price-feed/src/storage.rs +1 -1
  187. package/contracts/workers/price-feed/src/tests/mod.rs +2 -0
  188. package/contracts/workers/price-feed/src/tests/price_feed.rs +869 -0
  189. package/contracts/workers/price-feed/src/tests/setup.rs +70 -0
  190. package/contracts/workers/price-feed/src/types.rs +1 -1
  191. package/contracts/workers/worker/src/errors.rs +1 -4
  192. package/contracts/workers/worker/src/lib.rs +0 -2
  193. package/contracts/workers/worker/src/storage.rs +32 -29
  194. package/contracts/workers/worker/src/tests/setup.rs +2 -8
  195. package/contracts/workers/worker/src/tests/worker.rs +96 -74
  196. package/contracts/workers/worker/src/worker.rs +75 -75
  197. package/docs/error-spec.md +55 -0
  198. package/docs/layerzero-v2-on-stellar.md +447 -0
  199. package/docs/oapp-guide.md +212 -0
  200. package/docs/oft-guide.md +314 -0
  201. package/package.json +3 -3
  202. package/sdk/.turbo/turbo-test.log +268 -263
  203. package/sdk/dist/generated/bml.d.ts +12 -4
  204. package/sdk/dist/generated/bml.js +9 -7
  205. package/sdk/dist/generated/counter.d.ts +306 -298
  206. package/sdk/dist/generated/counter.js +48 -46
  207. package/sdk/dist/generated/dvn.d.ts +450 -411
  208. package/sdk/dist/generated/dvn.js +66 -64
  209. package/sdk/dist/generated/dvn_fee_lib.d.ts +294 -338
  210. package/sdk/dist/generated/dvn_fee_lib.js +33 -64
  211. package/sdk/dist/generated/endpoint.d.ts +108 -100
  212. package/sdk/dist/generated/endpoint.js +21 -19
  213. package/sdk/dist/generated/executor.d.ts +414 -370
  214. package/sdk/dist/generated/executor.js +58 -55
  215. package/sdk/dist/generated/executor_fee_lib.d.ts +333 -377
  216. package/sdk/dist/generated/executor_fee_lib.js +34 -65
  217. package/sdk/dist/generated/executor_helper.d.ts +26 -190
  218. package/sdk/dist/generated/executor_helper.js +23 -28
  219. package/sdk/dist/generated/layerzero_view.d.ts +1271 -0
  220. package/sdk/dist/generated/layerzero_view.js +294 -0
  221. package/sdk/dist/generated/oft.d.ts +408 -385
  222. package/sdk/dist/generated/oft.js +89 -92
  223. package/sdk/dist/generated/price_feed.d.ts +385 -429
  224. package/sdk/dist/generated/price_feed.js +50 -81
  225. package/sdk/dist/generated/sml.d.ts +108 -100
  226. package/sdk/dist/generated/sml.js +21 -19
  227. package/sdk/dist/generated/treasury.d.ts +108 -100
  228. package/sdk/dist/generated/treasury.js +21 -19
  229. package/sdk/dist/generated/uln302.d.ts +108 -100
  230. package/sdk/dist/generated/uln302.js +23 -21
  231. package/sdk/dist/generated/upgrader.d.ts +189 -18
  232. package/sdk/dist/generated/upgrader.js +84 -4
  233. package/sdk/dist/index.d.ts +1 -0
  234. package/sdk/dist/index.js +2 -0
  235. package/sdk/package.json +1 -1
  236. package/sdk/src/index.ts +3 -0
  237. package/sdk/test/oft-sml.test.ts +4 -4
  238. package/sdk/test/suites/localnet.ts +84 -20
  239. package/sdk/test/upgrader.test.ts +2 -3
  240. package/tools/ts-bindings-gen/src/main.rs +2 -1
  241. package/contracts/ERROR_SPEC.md +0 -44
  242. package/contracts/endpoint-v2/ARCHITECTURE.md +0 -233
  243. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +0 -175
  244. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +0 -212
  245. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +0 -153
  246. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +0 -294
  247. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/dvn_fee_lib.rs +0 -0
  248. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/executor_fee_lib.rs +0 -0
  249. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/price_feed.rs +0 -0
@@ -0,0 +1,569 @@
1
+ use crate::{self as oapp, errors::OAppError, oapp_receiver::LzReceiveInternal};
2
+ use endpoint_v2::{MessagingFee, MessagingParams, MessagingReceipt, Origin};
3
+ use soroban_sdk::{
4
+ contract, contractimpl, symbol_short,
5
+ testutils::{Address as _, MockAuth, MockAuthInvoke},
6
+ token::{StellarAssetClient, TokenClient},
7
+ Address, Bytes, BytesN, Env, IntoVal,
8
+ };
9
+
10
+ // Mock Endpoint contract
11
+ #[contract]
12
+ pub struct MockEndpoint;
13
+
14
+ #[contractimpl]
15
+ impl MockEndpoint {
16
+ pub fn __constructor(env: Env, zro_token: &Address, native_token: &Address) {
17
+ // Store as Option<Address> so zro() can return None when unavailable.
18
+ env.storage().instance().set(&symbol_short!("zro"), &Some(zro_token.clone()));
19
+ env.storage().instance().set(&symbol_short!("ntk"), native_token);
20
+ }
21
+
22
+ pub fn set_delegate(_env: Env, _oapp: Address, _delegate: Option<Address>) {
23
+ // do nothing in mock
24
+ }
25
+
26
+ pub fn quote(_env: Env, _sender: Address, params: MessagingParams) -> MessagingFee {
27
+ MessagingFee { native_fee: 1000, zro_fee: if params.pay_in_zro { 500 } else { 0 } }
28
+ }
29
+
30
+ pub fn send(env: Env, _sender: Address, params: MessagingParams, _refund_address: Address) -> MessagingReceipt {
31
+ // Record last send call for assertions
32
+ env.storage().instance().set(&symbol_short!("snds"), &_sender);
33
+ env.storage().instance().set(&symbol_short!("sndp"), &params);
34
+ env.storage().instance().set(&symbol_short!("sndr"), &_refund_address);
35
+
36
+ // Return mock receipt
37
+ MessagingReceipt {
38
+ guid: BytesN::from_array(&env, &[1u8; 32]),
39
+ nonce: 1,
40
+ fee: MessagingFee { native_fee: 1000, zro_fee: if params.pay_in_zro { 500 } else { 0 } },
41
+ }
42
+ }
43
+
44
+ pub fn last_send(env: Env) -> (Address, MessagingParams, Address) {
45
+ (
46
+ env.storage().instance().get(&symbol_short!("snds")).unwrap(),
47
+ env.storage().instance().get(&symbol_short!("sndp")).unwrap(),
48
+ env.storage().instance().get(&symbol_short!("sndr")).unwrap(),
49
+ )
50
+ }
51
+
52
+ pub fn zro(env: Env) -> Option<Address> {
53
+ // Return a mock ZRO token address (or None if not set)
54
+ env.storage().instance().get(&symbol_short!("zro")).unwrap_or(None)
55
+ }
56
+
57
+ pub fn native_token(env: Env) -> Address {
58
+ env.storage().instance().get(&symbol_short!("ntk")).unwrap()
59
+ }
60
+
61
+ pub fn set_zro(env: Env, zro: &Option<Address>) {
62
+ env.storage().instance().set(&symbol_short!("zro"), zro);
63
+ }
64
+ }
65
+
66
+ #[oapp_macros::oapp]
67
+ pub struct DummyOAppSender;
68
+
69
+ impl LzReceiveInternal for DummyOAppSender {
70
+ fn __lz_receive(
71
+ _env: &Env,
72
+ _origin: &Origin,
73
+ _guid: &BytesN<32>,
74
+ _message: &Bytes,
75
+ _extra_data: &Bytes,
76
+ _executor: &Address,
77
+ _value: i128,
78
+ ) {
79
+ // Not used in sender tests
80
+ }
81
+ }
82
+
83
+ #[contractimpl]
84
+ impl DummyOAppSender {
85
+ pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address) {
86
+ oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, &None);
87
+ }
88
+
89
+ pub fn quote(env: &Env, dst_eid: u32, message: &Bytes, options: &Bytes, pay_in_zro: bool) -> MessagingFee {
90
+ Self::__quote(env, dst_eid, message, options, pay_in_zro)
91
+ }
92
+
93
+ pub fn send(
94
+ env: &Env,
95
+ sender: &Address,
96
+ dst_eid: u32,
97
+ message: &Bytes,
98
+ options: &Bytes,
99
+ fee: &MessagingFee,
100
+ refund_address: &Address,
101
+ ) -> MessagingReceipt {
102
+ sender.require_auth();
103
+ Self::__lz_send(env, dst_eid, message, options, sender, fee, refund_address)
104
+ }
105
+
106
+ pub fn pay_native_fee(env: &Env, fee_payer: &Address, native_fee: i128) {
107
+ fee_payer.require_auth();
108
+ Self::__pay_native(env, fee_payer, native_fee)
109
+ }
110
+
111
+ pub fn pay_zro_fee(env: &Env, fee_payer: &Address, zro_fee: i128) {
112
+ fee_payer.require_auth();
113
+ Self::__pay_zro(env, fee_payer, zro_fee)
114
+ }
115
+ }
116
+
117
+ const REMOTE_EID: u32 = 100;
118
+ const UNSET_EID: u32 = 999;
119
+
120
+ struct TestSetup<'a> {
121
+ env: Env,
122
+ token_admin: Address,
123
+ endpoint: Address,
124
+ owner: Address,
125
+ oapp_client: DummyOAppSenderClient<'a>,
126
+ native_token: Address,
127
+ zro_token: Address,
128
+ native_token_client: TokenClient<'a>,
129
+ native_token_admin_client: StellarAssetClient<'a>,
130
+ zro_token_admin_client: StellarAssetClient<'a>,
131
+ }
132
+
133
+ fn setup<'a>() -> TestSetup<'a> {
134
+ let env = Env::default();
135
+
136
+ let owner = Address::generate(&env);
137
+
138
+ let token_admin = Address::generate(&env);
139
+ // Deploy mock tokens
140
+ let native_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
141
+ let native_token = native_token_sac.address();
142
+ let native_token_client = TokenClient::new(&env, &native_token);
143
+ let native_token_admin_client = StellarAssetClient::new(&env, &native_token);
144
+
145
+ let zro_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
146
+ let zro_token = zro_token_sac.address();
147
+ let zro_token_admin_client = StellarAssetClient::new(&env, &zro_token);
148
+
149
+ // Deploy mock endpoint
150
+ let endpoint = env.register(MockEndpoint, (&zro_token, &native_token));
151
+
152
+ // Deploy OApp
153
+ let oapp = env.register(DummyOAppSender, (&owner, &endpoint));
154
+ let oapp_client = DummyOAppSenderClient::new(&env, &oapp);
155
+
156
+ TestSetup {
157
+ env,
158
+ endpoint,
159
+ token_admin,
160
+ native_token_client,
161
+ native_token_admin_client,
162
+ zro_token_admin_client,
163
+ native_token,
164
+ zro_token,
165
+ owner,
166
+ oapp_client,
167
+ }
168
+ }
169
+
170
+ fn set_peer_with_auth(
171
+ env: &Env,
172
+ owner: &Address,
173
+ oapp_client: &DummyOAppSenderClient<'_>,
174
+ eid: u32,
175
+ peer: &BytesN<32>,
176
+ ) {
177
+ let peer_option = Some(peer.clone());
178
+ env.mock_auths(&[MockAuth {
179
+ address: owner,
180
+ invoke: &MockAuthInvoke {
181
+ contract: &oapp_client.address,
182
+ fn_name: "set_peer",
183
+ args: (&eid, &peer_option).into_val(env),
184
+ sub_invokes: &[],
185
+ },
186
+ }]);
187
+ oapp_client.set_peer(&eid, &peer_option);
188
+ }
189
+
190
+ fn mint_to(
191
+ env: &Env,
192
+ token_admin: &Address,
193
+ token: &Address,
194
+ token_admin_client: &StellarAssetClient<'_>,
195
+ to: &Address,
196
+ amount: i128,
197
+ ) {
198
+ env.mock_auths(&[MockAuth {
199
+ address: token_admin,
200
+ invoke: &MockAuthInvoke {
201
+ contract: token,
202
+ fn_name: "mint",
203
+ args: (to, amount).into_val(env),
204
+ sub_invokes: &[],
205
+ },
206
+ }]);
207
+ token_admin_client.mint(to, &amount);
208
+ }
209
+
210
+ fn mock_send_auth(
211
+ env: &Env,
212
+ sender: &Address,
213
+ oapp_client: &DummyOAppSenderClient<'_>,
214
+ dst_eid: u32,
215
+ message: &Bytes,
216
+ options: &Bytes,
217
+ fee: &MessagingFee,
218
+ refund_address: &Address,
219
+ native_token: &Address,
220
+ endpoint: &Address,
221
+ zro_token: &Address,
222
+ ) {
223
+ let native_transfer = MockAuthInvoke {
224
+ contract: native_token,
225
+ fn_name: "transfer",
226
+ args: (sender, endpoint, &fee.native_fee).into_val(env),
227
+ sub_invokes: &[],
228
+ };
229
+
230
+ if fee.zro_fee > 0 {
231
+ let zro_transfer = MockAuthInvoke {
232
+ contract: zro_token,
233
+ fn_name: "transfer",
234
+ args: (sender, endpoint, &fee.zro_fee).into_val(env),
235
+ sub_invokes: &[],
236
+ };
237
+ let sub_invokes = [native_transfer, zro_transfer];
238
+ env.mock_auths(&[MockAuth {
239
+ address: sender,
240
+ invoke: &MockAuthInvoke {
241
+ contract: &oapp_client.address,
242
+ fn_name: "send",
243
+ args: (sender, &dst_eid, message, options, fee, refund_address).into_val(env),
244
+ sub_invokes: &sub_invokes,
245
+ },
246
+ }]);
247
+ } else {
248
+ let sub_invokes = [native_transfer];
249
+ env.mock_auths(&[MockAuth {
250
+ address: sender,
251
+ invoke: &MockAuthInvoke {
252
+ contract: &oapp_client.address,
253
+ fn_name: "send",
254
+ args: (sender, &dst_eid, message, options, fee, refund_address).into_val(env),
255
+ sub_invokes: &sub_invokes,
256
+ },
257
+ }]);
258
+ }
259
+ }
260
+
261
+ #[test]
262
+ fn test_quote_with_peer_set() {
263
+ let TestSetup { env, owner, oapp_client, .. } = setup();
264
+
265
+ // Set peer for destination
266
+ let peer = BytesN::from_array(&env, &[1; 32]);
267
+ set_peer_with_auth(&env, &owner, &oapp_client, REMOTE_EID, &peer);
268
+
269
+ let message = Bytes::from_array(&env, &[1, 2, 3, 4, 5]);
270
+ let options = Bytes::from_array(&env, &[6, 7, 8]);
271
+
272
+ // Test quote without ZRO
273
+ let fee = oapp_client.quote(&REMOTE_EID, &message, &options, &false);
274
+ assert_eq!(fee.native_fee, 1000);
275
+ assert_eq!(fee.zro_fee, 0);
276
+
277
+ // Test quote with ZRO
278
+ let fee_with_zro = oapp_client.quote(&REMOTE_EID, &message, &options, &true);
279
+ assert_eq!(fee_with_zro.native_fee, 1000);
280
+ assert_eq!(fee_with_zro.zro_fee, 500);
281
+ }
282
+
283
+ #[test]
284
+ fn test_quote_without_peer_panics() {
285
+ let TestSetup { env, oapp_client, .. } = setup();
286
+
287
+ let message = Bytes::from_array(&env, &[1, 2, 3]);
288
+ let options = Bytes::from_array(&env, &[]);
289
+
290
+ // This should panic because no peer is set for UNSET_EID
291
+ let result = oapp_client.try_quote(&UNSET_EID, &message, &options, &false);
292
+ assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::NoPeer.into());
293
+ }
294
+
295
+ #[test]
296
+ fn test_lz_send_native_only() {
297
+ let TestSetup {
298
+ env,
299
+ oapp_client,
300
+ endpoint,
301
+ native_token,
302
+ zro_token,
303
+ native_token_client,
304
+ native_token_admin_client,
305
+ token_admin,
306
+ owner,
307
+ ..
308
+ } = setup();
309
+
310
+ // Setup peer
311
+ let peer = BytesN::from_array(&env, &[2; 32]);
312
+ set_peer_with_auth(&env, &owner, &oapp_client, REMOTE_EID, &peer);
313
+
314
+ let sender = Address::generate(&env);
315
+ mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &sender, 1000i128);
316
+
317
+ let message = Bytes::from_array(&env, &[1, 2, 3]);
318
+ let options = Bytes::from_array(&env, &[]);
319
+ let refund_address = Address::generate(&env);
320
+ let fee = MessagingFee { native_fee: 1000, zro_fee: 0 };
321
+
322
+ mock_send_auth(
323
+ &env,
324
+ &sender,
325
+ &oapp_client,
326
+ REMOTE_EID,
327
+ &message,
328
+ &options,
329
+ &fee,
330
+ &refund_address,
331
+ &native_token,
332
+ &endpoint,
333
+ &zro_token,
334
+ );
335
+ let receipt = oapp_client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund_address);
336
+
337
+ assert_eq!(receipt.nonce, 1);
338
+ assert_eq!(receipt.fee.native_fee, 1000);
339
+ assert_eq!(receipt.fee.zro_fee, 0);
340
+
341
+ // Assert the endpoint received the correct send params
342
+ let endpoint_client = MockEndpointClient::new(&env, &endpoint);
343
+ let (endpoint_sender, params, refund) = endpoint_client.last_send();
344
+ assert_eq!(endpoint_sender, oapp_client.address);
345
+ assert_eq!(params.dst_eid, REMOTE_EID);
346
+ assert_eq!(params.receiver, peer);
347
+ assert_eq!(params.message, message);
348
+ assert_eq!(params.options, options);
349
+ assert_eq!(params.pay_in_zro, false);
350
+ assert_eq!(refund, refund_address);
351
+
352
+ assert_eq!(native_token_client.balance(&sender), 0);
353
+ assert_eq!(native_token_client.balance(&endpoint), 1000);
354
+ assert_eq!(TokenClient::new(&env, &zro_token).balance(&endpoint), 0);
355
+ }
356
+
357
+ #[test]
358
+ fn test_lz_send_with_zro() {
359
+ let TestSetup {
360
+ env,
361
+ oapp_client,
362
+ endpoint,
363
+ native_token,
364
+ zro_token,
365
+ native_token_client,
366
+ native_token_admin_client,
367
+ zro_token_admin_client,
368
+ token_admin,
369
+ owner,
370
+ ..
371
+ } = setup();
372
+
373
+ // Setup peer
374
+ let peer = BytesN::from_array(&env, &[3; 32]);
375
+ set_peer_with_auth(&env, &owner, &oapp_client, REMOTE_EID, &peer);
376
+
377
+ let sender = Address::generate(&env);
378
+ let fee = MessagingFee { native_fee: 1000, zro_fee: 500 };
379
+ mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &sender, fee.native_fee);
380
+ mint_to(&env, &token_admin, &zro_token, &zro_token_admin_client, &sender, fee.zro_fee);
381
+
382
+ let message = Bytes::from_array(&env, &[4, 5, 6]);
383
+ let options = Bytes::from_array(&env, &[7]);
384
+ let refund_address = Address::generate(&env);
385
+
386
+ mock_send_auth(
387
+ &env,
388
+ &sender,
389
+ &oapp_client,
390
+ REMOTE_EID,
391
+ &message,
392
+ &options,
393
+ &fee,
394
+ &refund_address,
395
+ &native_token,
396
+ &endpoint,
397
+ &zro_token,
398
+ );
399
+ let receipt = oapp_client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund_address);
400
+
401
+ assert_eq!(receipt.nonce, 1);
402
+ assert_eq!(receipt.fee.native_fee, 1000);
403
+ assert_eq!(receipt.fee.zro_fee, 500);
404
+
405
+ // Assert the endpoint received the correct send params
406
+ let endpoint_client = MockEndpointClient::new(&env, &endpoint);
407
+ let (endpoint_sender, params, refund) = endpoint_client.last_send();
408
+ assert_eq!(endpoint_sender, oapp_client.address);
409
+ assert_eq!(params.dst_eid, REMOTE_EID);
410
+ assert_eq!(params.receiver, peer);
411
+ assert_eq!(params.message, message);
412
+ assert_eq!(params.options, options);
413
+ assert_eq!(params.pay_in_zro, true);
414
+ assert_eq!(refund, refund_address);
415
+
416
+ assert_eq!(native_token_client.balance(&sender), 0);
417
+ assert_eq!(native_token_client.balance(&endpoint), 1000);
418
+
419
+ let zro_token_client = TokenClient::new(&env, &zro_token);
420
+ assert_eq!(zro_token_client.balance(&sender), 0);
421
+ assert_eq!(zro_token_client.balance(&endpoint), 500);
422
+ }
423
+
424
+ #[test]
425
+ fn test_pay_native() {
426
+ let TestSetup { env, oapp_client, endpoint, native_token, native_token_admin_client, token_admin, .. } = setup();
427
+
428
+ let payer = Address::generate(&env);
429
+ let payment_amount = 2000i128;
430
+
431
+ // Fund the payer
432
+ mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &payer, payment_amount);
433
+
434
+ // Make payment
435
+ env.mock_auths(&[MockAuth {
436
+ address: &payer,
437
+ invoke: &MockAuthInvoke {
438
+ contract: &oapp_client.address,
439
+ fn_name: "pay_native_fee",
440
+ args: (&payer, &payment_amount).into_val(&env),
441
+ sub_invokes: &[MockAuthInvoke {
442
+ contract: &native_token,
443
+ fn_name: "transfer",
444
+ args: (&payer, &endpoint, &payment_amount).into_val(&env),
445
+ sub_invokes: &[],
446
+ }],
447
+ },
448
+ }]);
449
+ oapp_client.pay_native_fee(&payer, &payment_amount);
450
+
451
+ // Verify balances
452
+ assert_eq!(native_token_admin_client.balance(&payer), 0);
453
+ assert_eq!(native_token_admin_client.balance(&endpoint), payment_amount);
454
+ }
455
+
456
+ #[test]
457
+ #[should_panic(expected = "balance is not sufficient to spend")]
458
+ fn test_pay_native_insufficient_balance() {
459
+ let TestSetup { env, oapp_client, endpoint, native_token, native_token_admin_client, token_admin, .. } = setup();
460
+
461
+ let balance = 500i128;
462
+ let payment_amount = 1000i128;
463
+
464
+ let payer = Address::generate(&env);
465
+
466
+ // Fund with less than required
467
+ mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &payer, balance);
468
+
469
+ // This should panic due to insufficient balance
470
+ env.mock_auths(&[MockAuth {
471
+ address: &payer,
472
+ invoke: &MockAuthInvoke {
473
+ contract: &oapp_client.address,
474
+ fn_name: "pay_native_fee",
475
+ args: (&payer, &payment_amount).into_val(&env),
476
+ sub_invokes: &[MockAuthInvoke {
477
+ contract: &native_token,
478
+ fn_name: "transfer",
479
+ args: (&payer, &endpoint, &payment_amount).into_val(&env),
480
+ sub_invokes: &[],
481
+ }],
482
+ },
483
+ }]);
484
+ oapp_client.pay_native_fee(&payer, &payment_amount);
485
+ }
486
+
487
+ #[test]
488
+ fn test_pay_zro_success() {
489
+ let TestSetup { env, oapp_client, endpoint, zro_token, zro_token_admin_client, token_admin, .. } = setup();
490
+
491
+ let payer = Address::generate(&env);
492
+ let payment_amount = 500i128;
493
+ mint_to(&env, &token_admin, &zro_token, &zro_token_admin_client, &payer, payment_amount);
494
+
495
+ env.mock_auths(&[MockAuth {
496
+ address: &payer,
497
+ invoke: &MockAuthInvoke {
498
+ contract: &oapp_client.address,
499
+ fn_name: "pay_zro_fee",
500
+ args: (&payer, &payment_amount).into_val(&env),
501
+ sub_invokes: &[MockAuthInvoke {
502
+ contract: &zro_token,
503
+ fn_name: "transfer",
504
+ args: (&payer, &endpoint, &payment_amount).into_val(&env),
505
+ sub_invokes: &[],
506
+ }],
507
+ },
508
+ }]);
509
+ oapp_client.pay_zro_fee(&payer, &payment_amount);
510
+
511
+ assert_eq!(zro_token_admin_client.balance(&payer), 0);
512
+ assert_eq!(zro_token_admin_client.balance(&endpoint), payment_amount);
513
+ }
514
+
515
+ #[test]
516
+ #[should_panic(expected = "balance is not sufficient to spend")]
517
+ fn test_pay_zro_insufficient_balance() {
518
+ let TestSetup { env, oapp_client, endpoint, zro_token, zro_token_admin_client, token_admin, .. } = setup();
519
+
520
+ let payer = Address::generate(&env);
521
+ let balance = 100i128;
522
+ let payment_amount = 500i128;
523
+
524
+ // Fund with less than required
525
+ mint_to(&env, &token_admin, &zro_token, &zro_token_admin_client, &payer, balance);
526
+
527
+ env.mock_auths(&[MockAuth {
528
+ address: &payer,
529
+ invoke: &MockAuthInvoke {
530
+ contract: &oapp_client.address,
531
+ fn_name: "pay_zro_fee",
532
+ args: (&payer, &payment_amount).into_val(&env),
533
+ sub_invokes: &[MockAuthInvoke {
534
+ contract: &zro_token,
535
+ fn_name: "transfer",
536
+ args: (&payer, &endpoint, &payment_amount).into_val(&env),
537
+ sub_invokes: &[],
538
+ }],
539
+ },
540
+ }]);
541
+ oapp_client.pay_zro_fee(&payer, &payment_amount);
542
+ }
543
+
544
+ #[test]
545
+ fn test_pay_zro_unavailable_returns_error() {
546
+ let TestSetup { env, oapp_client, endpoint, zro_token, .. } = setup();
547
+
548
+ let endpoint_client = MockEndpointClient::new(&env, &endpoint);
549
+ endpoint_client.set_zro(&None);
550
+
551
+ let payer = Address::generate(&env);
552
+ let payment_amount = 500i128;
553
+
554
+ env.mock_auths(&[MockAuth {
555
+ address: &payer,
556
+ invoke: &MockAuthInvoke {
557
+ contract: &oapp_client.address,
558
+ fn_name: "pay_zro_fee",
559
+ args: (&payer, &payment_amount).into_val(&env),
560
+ sub_invokes: &[],
561
+ },
562
+ }]);
563
+ let result = oapp_client.try_pay_zro_fee(&payer, &payment_amount);
564
+ assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::ZroTokenUnavailable.into());
565
+
566
+ // Ensure we did not transfer any ZRO accidentally
567
+ let token_client = TokenClient::new(&env, &zro_token);
568
+ assert_eq!(token_client.balance(&payer), 0);
569
+ }
@@ -9,7 +9,11 @@ publish = false
9
9
  proc-macro = true
10
10
 
11
11
  [dependencies]
12
- heck = "0.5"
13
- proc-macro2 = "1.0"
14
- quote = "1.0"
15
- syn = { version = "2.0", features = ["full", "extra-traits"] }
12
+ heck = { workspace = true }
13
+ proc-macro2 = { workspace = true }
14
+ quote = { workspace = true }
15
+ syn = { workspace = true }
16
+
17
+ [dev-dependencies]
18
+ insta = { workspace = true }
19
+ prettyplease = { workspace = true }
@@ -1,7 +1,6 @@
1
1
  //! Code generators for OApp trait implementations.
2
2
 
3
3
  use crate::CustomImpls;
4
- use heck::ToSnakeCase;
5
4
  use proc_macro2::TokenStream;
6
5
  use quote::quote;
7
6
  use syn::{Ident, ItemStruct};
@@ -43,17 +42,11 @@ fn generate_oapp_core(name: &Ident, custom: bool) -> TokenStream {
43
42
  return TokenStream::new();
44
43
  }
45
44
 
46
- let impl_mod = impl_mod_ident(name, "core");
47
-
48
45
  quote! {
49
- #[doc(hidden)]
50
- mod #impl_mod {
51
- use super::*;
52
- use oapp::oapp_core::OAppCore;
46
+ use oapp::oapp_core::OAppCore as _;
53
47
 
54
- #[soroban_sdk::contractimpl(contracttrait)]
55
- impl OAppCore for #name {}
56
- }
48
+ #[soroban_sdk::contractimpl(contracttrait)]
49
+ impl oapp::oapp_core::OAppCore for #name {}
57
50
  }
58
51
  }
59
52
 
@@ -84,17 +77,11 @@ fn generate_oapp_receiver(name: &Ident, custom: bool) -> TokenStream {
84
77
  return TokenStream::new();
85
78
  }
86
79
 
87
- let impl_mod = impl_mod_ident(name, "receiver");
88
-
89
80
  quote! {
90
- #[doc(hidden)]
91
- mod #impl_mod {
92
- use super::*;
93
- use oapp::oapp_receiver::OAppReceiver;
81
+ use oapp::oapp_receiver::OAppReceiver as _;
94
82
 
95
- #[soroban_sdk::contractimpl(contracttrait)]
96
- impl OAppReceiver for #name {}
97
- }
83
+ #[soroban_sdk::contractimpl(contracttrait)]
84
+ impl oapp::oapp_receiver::OAppReceiver for #name {}
98
85
  }
99
86
  }
100
87
 
@@ -107,22 +94,10 @@ fn generate_oapp_options_type3(name: &Ident, custom: bool) -> TokenStream {
107
94
  return TokenStream::new();
108
95
  }
109
96
 
110
- let impl_mod = impl_mod_ident(name, "options_type3");
111
-
112
97
  quote! {
113
- #[doc(hidden)]
114
- mod #impl_mod {
115
- use super::*;
116
- use soroban_sdk::Vec;
117
- use oapp::oapp_options_type3::{EnforcedOptionParam, OAppOptionsType3};
98
+ use oapp::oapp_options_type3::OAppOptionsType3 as _;
118
99
 
119
- #[soroban_sdk::contractimpl(contracttrait)]
120
- impl OAppOptionsType3 for #name {}
121
- }
100
+ #[soroban_sdk::contractimpl(contracttrait)]
101
+ impl oapp::oapp_options_type3::OAppOptionsType3 for #name {}
122
102
  }
123
103
  }
124
-
125
- /// Creates a unique hidden module identifier for trait implementations.
126
- fn impl_mod_ident(struct_name: &Ident, trait_name: &str) -> Ident {
127
- Ident::new(&format!("__oapp_{}_impl_{}", trait_name, struct_name.to_string().to_snake_case()), struct_name.span())
128
- }
@@ -132,6 +132,9 @@ use syn::{
132
132
  Error, Ident, ItemStruct, Token,
133
133
  };
134
134
 
135
+ #[cfg(test)]
136
+ mod tests;
137
+
135
138
  /// Derives a complete OApp: `#[contract]` + `#[ownable]` + Core + Sender + Receiver + OptionsType3.
136
139
  ///
137
140
  /// ## Usage
@@ -0,0 +1,2 @@
1
+ mod oapp;
2
+ mod parse_custom_impls;