@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,88 @@
1
+ use quote::quote;
2
+
3
+ // ============================================
4
+ // Snapshot Tests: OApp Code Generation
5
+ // ============================================
6
+
7
+ #[test]
8
+ fn snapshot_generate_oapp() {
9
+ let input = quote! {
10
+ pub struct MyOApp;
11
+ };
12
+ let item_struct: syn::ItemStruct = syn::parse2(input).expect("failed to parse struct");
13
+
14
+ let all_defaults = {
15
+ let result = crate::generators::generate_oapp(item_struct.clone(), crate::CustomImpls::default());
16
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
17
+ };
18
+
19
+ let custom_core_only = {
20
+ let result = crate::generators::generate_oapp(
21
+ item_struct.clone(),
22
+ crate::CustomImpls { core: true, sender: false, receiver: false, options_type3: false },
23
+ );
24
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
25
+ };
26
+
27
+ let custom_sender_only = {
28
+ let result = crate::generators::generate_oapp(
29
+ item_struct.clone(),
30
+ crate::CustomImpls { core: false, sender: true, receiver: false, options_type3: false },
31
+ );
32
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
33
+ };
34
+
35
+ let custom_receiver_only = {
36
+ let result = crate::generators::generate_oapp(
37
+ item_struct.clone(),
38
+ crate::CustomImpls { core: false, sender: false, receiver: true, options_type3: false },
39
+ );
40
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
41
+ };
42
+
43
+ let custom_options_type3_only = {
44
+ let result = crate::generators::generate_oapp(
45
+ item_struct.clone(),
46
+ crate::CustomImpls { core: false, sender: false, receiver: false, options_type3: true },
47
+ );
48
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
49
+ };
50
+
51
+ let custom_all = {
52
+ let result = crate::generators::generate_oapp(
53
+ item_struct.clone(),
54
+ crate::CustomImpls { core: true, sender: true, receiver: true, options_type3: true },
55
+ );
56
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
57
+ };
58
+
59
+ let preserves_struct_attributes_and_fields = {
60
+ let fancy_input = quote! {
61
+ #[derive(Clone, Debug)]
62
+ pub struct FancyOApp {
63
+ pub x: u32,
64
+ }
65
+ };
66
+ let fancy_struct: syn::ItemStruct = syn::parse2(fancy_input).expect("failed to parse struct");
67
+ let result = crate::generators::generate_oapp(fancy_struct, crate::CustomImpls::default());
68
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
69
+ };
70
+
71
+ let combined = format!(
72
+ "// === Default (no custom impls) ===\n\n{}\n\n\
73
+ // === custom = [core] ===\n\n{}\n\n\
74
+ // === custom = [sender] ===\n\n{}\n\n\
75
+ // === custom = [receiver] ===\n\n{}\n\n\
76
+ // === custom = [options_type3] ===\n\n{}\n\n\
77
+ // === custom = [core, sender, receiver, options_type3] ===\n\n{}\n\n\
78
+ // === Struct attributes + fields are preserved ===\n\n{}",
79
+ all_defaults,
80
+ custom_core_only,
81
+ custom_sender_only,
82
+ custom_receiver_only,
83
+ custom_options_type3_only,
84
+ custom_all,
85
+ preserves_struct_attributes_and_fields
86
+ );
87
+ insta::assert_snapshot!(combined);
88
+ }
@@ -0,0 +1,86 @@
1
+ use quote::quote;
2
+
3
+ // ============================================
4
+ // Unit Tests: #[oapp(custom = [...])] parsing
5
+ // ============================================
6
+
7
+ #[test]
8
+ fn test_custom_impls_parse_empty_is_default() {
9
+ let parsed: crate::CustomImpls = syn::parse2(quote! {}).expect("failed to parse empty attrs");
10
+ assert!(!parsed.core);
11
+ assert!(!parsed.sender);
12
+ assert!(!parsed.receiver);
13
+ assert!(!parsed.options_type3);
14
+ }
15
+
16
+ #[test]
17
+ fn test_custom_impls_parse_valid_all_list() {
18
+ let parsed: crate::CustomImpls =
19
+ syn::parse2(quote! { custom = [core, sender, receiver, options_type3] }).expect("failed to parse attrs");
20
+ assert!(parsed.core);
21
+ assert!(parsed.sender);
22
+ assert!(parsed.receiver);
23
+ assert!(parsed.options_type3);
24
+ }
25
+
26
+ #[test]
27
+ fn test_custom_impls_parse_empty_custom_list_is_default() {
28
+ let parsed: crate::CustomImpls = syn::parse2(quote! { custom = [] }).expect("failed to parse attrs");
29
+ assert!(!parsed.core);
30
+ assert!(!parsed.sender);
31
+ assert!(!parsed.receiver);
32
+ assert!(!parsed.options_type3);
33
+ }
34
+
35
+ #[test]
36
+ fn test_custom_impls_allows_trailing_comma() {
37
+ let parsed: crate::CustomImpls = syn::parse2(quote! { custom = [core,] }).expect("failed to parse attrs");
38
+ assert!(parsed.core);
39
+ assert!(!parsed.sender);
40
+ assert!(!parsed.receiver);
41
+ assert!(!parsed.options_type3);
42
+ }
43
+
44
+ #[test]
45
+ fn test_custom_impls_allows_duplicates() {
46
+ // Duplicates are harmless and should not cause parsing to fail.
47
+ let parsed: crate::CustomImpls =
48
+ syn::parse2(quote! { custom = [core, core, receiver, receiver] }).expect("failed to parse attrs");
49
+ assert!(parsed.core);
50
+ assert!(!parsed.sender);
51
+ assert!(parsed.receiver);
52
+ assert!(!parsed.options_type3);
53
+ }
54
+
55
+ #[test]
56
+ fn test_custom_impls_rejects_wrong_key() {
57
+ let err = syn::parse2::<crate::CustomImpls>(quote! { nope = [core] }).expect_err("expected parse failure");
58
+ assert!(err.to_string().contains("expected `custom`"), "unexpected error: {err}");
59
+ }
60
+
61
+ #[test]
62
+ fn test_custom_impls_rejects_unknown_ident() {
63
+ let err =
64
+ syn::parse2::<crate::CustomImpls>(quote! { custom = [core, not_a_real_option] }).expect_err("expected failure");
65
+ assert!(
66
+ err.to_string().contains("expected one of `core`, `sender`, `receiver`, `options_type3`"),
67
+ "unexpected error: {err}"
68
+ );
69
+ }
70
+
71
+ #[test]
72
+ fn test_custom_impls_rejects_trailing_tokens_after_list() {
73
+ // `syn::parse2` expects the parser to consume the full stream.
74
+ syn::parse2::<crate::CustomImpls>(quote! { custom = [core] extra })
75
+ .expect_err("expected parse failure due to trailing tokens");
76
+ }
77
+
78
+ #[test]
79
+ fn test_custom_impls_rejects_missing_equals() {
80
+ syn::parse2::<crate::CustomImpls>(quote! { custom [core] }).expect_err("expected parse failure (missing `=`)");
81
+ }
82
+
83
+ #[test]
84
+ fn test_custom_impls_rejects_non_bracketed_list() {
85
+ syn::parse2::<crate::CustomImpls>(quote! { custom = (core) }).expect_err("expected parse failure (not `[...]`)");
86
+ }
@@ -0,0 +1,103 @@
1
+ ---
2
+ source: contracts/oapps/oapp-macros/src/tests/oapp.rs
3
+ assertion_line: 87
4
+ expression: combined
5
+ ---
6
+ // === Default (no custom impls) ===
7
+
8
+ #[common_macros::lz_contract]
9
+ pub struct MyOApp;
10
+ use oapp::oapp_core::OAppCore as _;
11
+ #[soroban_sdk::contractimpl(contracttrait)]
12
+ impl oapp::oapp_core::OAppCore for MyOApp {}
13
+ use oapp::oapp_sender::OAppSenderInternal as _;
14
+ impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
15
+ use oapp::oapp_receiver::OAppReceiver as _;
16
+ #[soroban_sdk::contractimpl(contracttrait)]
17
+ impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
18
+ use oapp::oapp_options_type3::OAppOptionsType3 as _;
19
+ #[soroban_sdk::contractimpl(contracttrait)]
20
+ impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
21
+
22
+
23
+ // === custom = [core] ===
24
+
25
+ #[common_macros::lz_contract]
26
+ pub struct MyOApp;
27
+ use oapp::oapp_sender::OAppSenderInternal as _;
28
+ impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
29
+ use oapp::oapp_receiver::OAppReceiver as _;
30
+ #[soroban_sdk::contractimpl(contracttrait)]
31
+ impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
32
+ use oapp::oapp_options_type3::OAppOptionsType3 as _;
33
+ #[soroban_sdk::contractimpl(contracttrait)]
34
+ impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
35
+
36
+
37
+ // === custom = [sender] ===
38
+
39
+ #[common_macros::lz_contract]
40
+ pub struct MyOApp;
41
+ use oapp::oapp_core::OAppCore as _;
42
+ #[soroban_sdk::contractimpl(contracttrait)]
43
+ impl oapp::oapp_core::OAppCore for MyOApp {}
44
+ use oapp::oapp_receiver::OAppReceiver as _;
45
+ #[soroban_sdk::contractimpl(contracttrait)]
46
+ impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
47
+ use oapp::oapp_options_type3::OAppOptionsType3 as _;
48
+ #[soroban_sdk::contractimpl(contracttrait)]
49
+ impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
50
+
51
+
52
+ // === custom = [receiver] ===
53
+
54
+ #[common_macros::lz_contract]
55
+ pub struct MyOApp;
56
+ use oapp::oapp_core::OAppCore as _;
57
+ #[soroban_sdk::contractimpl(contracttrait)]
58
+ impl oapp::oapp_core::OAppCore for MyOApp {}
59
+ use oapp::oapp_sender::OAppSenderInternal as _;
60
+ impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
61
+ use oapp::oapp_options_type3::OAppOptionsType3 as _;
62
+ #[soroban_sdk::contractimpl(contracttrait)]
63
+ impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
64
+
65
+
66
+ // === custom = [options_type3] ===
67
+
68
+ #[common_macros::lz_contract]
69
+ pub struct MyOApp;
70
+ use oapp::oapp_core::OAppCore as _;
71
+ #[soroban_sdk::contractimpl(contracttrait)]
72
+ impl oapp::oapp_core::OAppCore for MyOApp {}
73
+ use oapp::oapp_sender::OAppSenderInternal as _;
74
+ impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
75
+ use oapp::oapp_receiver::OAppReceiver as _;
76
+ #[soroban_sdk::contractimpl(contracttrait)]
77
+ impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
78
+
79
+
80
+ // === custom = [core, sender, receiver, options_type3] ===
81
+
82
+ #[common_macros::lz_contract]
83
+ pub struct MyOApp;
84
+
85
+
86
+ // === Struct attributes + fields are preserved ===
87
+
88
+ #[common_macros::lz_contract]
89
+ #[derive(Clone, Debug)]
90
+ pub struct FancyOApp {
91
+ pub x: u32,
92
+ }
93
+ use oapp::oapp_core::OAppCore as _;
94
+ #[soroban_sdk::contractimpl(contracttrait)]
95
+ impl oapp::oapp_core::OAppCore for FancyOApp {}
96
+ use oapp::oapp_sender::OAppSenderInternal as _;
97
+ impl oapp::oapp_sender::OAppSenderInternal for FancyOApp {}
98
+ use oapp::oapp_receiver::OAppReceiver as _;
99
+ #[soroban_sdk::contractimpl(contracttrait)]
100
+ impl oapp::oapp_receiver::OAppReceiver for FancyOApp {}
101
+ use oapp::oapp_options_type3::OAppOptionsType3 as _;
102
+ #[soroban_sdk::contractimpl(contracttrait)]
103
+ impl oapp::oapp_options_type3::OAppOptionsType3 for FancyOApp {}
@@ -1,6 +1,6 @@
1
1
  //! Utility functions for OFT-STD integration tests.
2
2
 
3
- use crate::extensions::rate_limiter::Direction;
3
+ use crate::extensions::rate_limiter::{Direction, RateLimitConfig};
4
4
  use crate::integration_tests::setup::{decode_packet, ChainSetup};
5
5
  use endpoint_v2::{MessagingFee, Origin, OutboundPacket};
6
6
  use message_lib_common::packet_codec_v1;
@@ -254,10 +254,28 @@ pub fn try_lz_receive(
254
254
 
255
255
  // returns (encoded_payload, options, send_library)
256
256
  pub fn scan_packet_sent_event(env: &Env, endpoint: &Address) -> Option<(Bytes, Bytes, Address)> {
257
+ use soroban_sdk::TryFromVal;
258
+
257
259
  let mut packet = None;
258
- for (emitter, topics, data) in env.events().all() {
259
- let packet_sent_symbol = Symbol::new(env, "packet_sent").to_val();
260
- if emitter == *endpoint && topics.contains(packet_sent_symbol) {
260
+ let events = env.events().all().filter_by_contract(endpoint);
261
+ for event in events.events().iter() {
262
+ let v0 = match &event.body {
263
+ soroban_sdk::xdr::ContractEventBody::V0(v0) => v0,
264
+ };
265
+
266
+ // Check if this is a packet_sent event by looking at topics
267
+ let mut is_packet_sent = false;
268
+ for topic in v0.topics.iter() {
269
+ if let Ok(sym) = Symbol::try_from_val(env, topic) {
270
+ if sym == Symbol::new(env, "packet_sent") {
271
+ is_packet_sent = true;
272
+ break;
273
+ }
274
+ }
275
+ }
276
+
277
+ if is_packet_sent {
278
+ let data: Val = Val::try_from_val(env, &v0.data).unwrap();
261
279
  let map: Map<Symbol, Val> = data.into_val(env);
262
280
 
263
281
  let encoded_payload: Bytes = map.get(Symbol::new(env, "encoded_packet")).unwrap().into_val(env);
@@ -359,16 +377,17 @@ pub fn set_default_fee_bps(env: &Env, chain: &ChainSetup<'_>, fee_bps: u64) {
359
377
  }
360
378
 
361
379
  pub fn set_fee_bps(env: &Env, chain: &ChainSetup<'_>, dst_eid: u32, fee_bps: u64) {
380
+ let fee_bps_opt = Some(fee_bps);
362
381
  env.mock_auths(&[MockAuth {
363
382
  address: &chain.owner,
364
383
  invoke: &MockAuthInvoke {
365
384
  contract: &chain.oft.address,
366
385
  fn_name: "set_fee_bps",
367
- args: (&dst_eid, &fee_bps).into_val(env),
386
+ args: (&dst_eid, &fee_bps_opt).into_val(env),
368
387
  sub_invokes: &[],
369
388
  },
370
389
  }]);
371
- chain.oft.set_fee_bps(&dst_eid, &fee_bps);
390
+ chain.oft.set_fee_bps(&dst_eid, &fee_bps_opt);
372
391
  }
373
392
 
374
393
  // ============================================================================
@@ -383,16 +402,17 @@ pub fn set_rate_limit(
383
402
  limit: i128,
384
403
  window_seconds: u64,
385
404
  ) {
405
+ let config = Some(RateLimitConfig { limit, window_seconds });
386
406
  env.mock_auths(&[MockAuth {
387
407
  address: &chain.owner,
388
408
  invoke: &MockAuthInvoke {
389
409
  contract: &chain.oft.address,
390
410
  fn_name: "set_rate_limit",
391
- args: (direction, &dst_eid, &limit, &window_seconds).into_val(env),
411
+ args: (direction, &dst_eid, &config).into_val(env),
392
412
  sub_invokes: &[],
393
413
  },
394
414
  }]);
395
- chain.oft.set_rate_limit(direction, &dst_eid, &limit, &window_seconds);
415
+ chain.oft.set_rate_limit(direction, &dst_eid, &config);
396
416
  }
397
417
 
398
418
  pub fn rate_limit_capacity(chain: &ChainSetup<'_>, direction: &Direction, eid: u32) -> i128 {
@@ -1,32 +1,48 @@
1
1
  use common_macros::{contract_error, contract_trait, only_auth, storage};
2
2
  use soroban_sdk::{assert_with_error, contractevent, token::TokenClient, Address, Env};
3
- use utils::{option_ext::OptionExt, ownable::Ownable};
3
+ use utils::{auth::Auth, option_ext::OptionExt};
4
4
 
5
5
  /// Base fee in basis points (10,000 BPS = 100%)
6
6
  /// Used as denominator in fee calculations
7
7
  const BASE_FEE_BPS: u64 = 10_000;
8
8
 
9
+ // =========================================================================
10
+ // Storage
11
+ // =========================================================================
12
+
9
13
  #[storage]
10
14
  pub enum OFTFeeStorage {
15
+ /// Default fee rate in basis points (0-10,000, where 10,000 = 100%)
16
+ /// Applied to destinations without specific fee configuration
17
+ /// No fee is charged(default to 0) by default
11
18
  #[instance(u64)]
12
19
  #[default(0)]
13
20
  DefaultFeeBps,
14
21
 
22
+ /// Destination-specific fee rates mapped by endpoint ID (eid)
15
23
  #[persistent(u64)]
16
24
  FeeBps { eid: u32 },
17
25
 
26
+ /// Address where collected fees will be deposited
18
27
  #[instance(Address)]
19
28
  FeeDepositAddress,
20
29
  }
21
30
 
31
+ // =========================================================================
32
+ // Errors
33
+ // =========================================================================
34
+
22
35
  #[contract_error]
23
36
  pub enum OFTFeeError {
24
- InvalidFeeBps = 2200,
37
+ InvalidFeeBps = 3100,
25
38
  InvalidFeeDepositAddress,
26
- NotFound,
27
39
  SameValue,
28
40
  }
29
41
 
42
+ // =========================================================================
43
+ // Events
44
+ // =========================================================================
45
+
30
46
  #[contractevent]
31
47
  #[derive(Clone, Debug, Eq, PartialEq)]
32
48
  pub struct DefaultFeeBpsSet {
@@ -37,13 +53,8 @@ pub struct DefaultFeeBpsSet {
37
53
  #[derive(Clone, Debug, Eq, PartialEq)]
38
54
  pub struct FeeBpsSet {
39
55
  pub dst_eid: u32,
40
- pub fee_bps: u64,
41
- }
42
-
43
- #[contractevent]
44
- #[derive(Clone, Debug, Eq, PartialEq)]
45
- pub struct FeeBpsUnset {
46
- pub dst_eid: u32,
56
+ /// The fee rate in basis points, or None if the fee is removed
57
+ pub fee_bps: Option<u64>,
47
58
  }
48
59
 
49
60
  #[contractevent]
@@ -52,72 +63,70 @@ pub struct FeeDepositAddressSet {
52
63
  pub fee_deposit_address: Address,
53
64
  }
54
65
 
66
+ // =========================================================================
67
+ // Trait With Default Implementations
68
+ // =========================================================================
69
+
55
70
  #[contract_trait]
56
- pub trait OFTFee: OFTFeeInternal + Ownable + Sized {
57
- #[only_auth]
58
- fn set_default_fee_bps(env: &Env, default_fee_bps: u64) {
59
- assert_with_error!(env, default_fee_bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
60
- let current_default = OFTFeeStorage::default_fee_bps(env);
61
- assert_with_error!(env, current_default != default_fee_bps, OFTFeeError::SameValue);
62
- OFTFeeStorage::set_default_fee_bps(env, &default_fee_bps);
63
- DefaultFeeBpsSet { fee_bps: default_fee_bps }.publish(env);
64
- }
71
+ pub trait OFTFee: OFTFeeInternal + Auth {
72
+ // =========================================================================
73
+ // Management Functions
74
+ // =========================================================================
65
75
 
76
+ /// Sets the default fee rate in basis points.
66
77
  #[only_auth]
67
- fn set_fee_bps(env: &Env, dst_eid: u32, fee_bps: u64) {
68
- assert_with_error!(env, fee_bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
69
- if OFTFeeStorage::has_fee_bps(env, dst_eid) {
70
- let current_fee_bps = OFTFeeStorage::fee_bps(env, dst_eid).unwrap();
71
- assert_with_error!(env, current_fee_bps != fee_bps, OFTFeeError::SameValue);
72
- }
73
- OFTFeeStorage::set_fee_bps(env, dst_eid, &fee_bps);
74
- FeeBpsSet { dst_eid, fee_bps }.publish(env);
78
+ fn set_default_fee_bps(env: &soroban_sdk::Env, default_fee_bps: u64) {
79
+ Self::__set_default_fee_bps(env, default_fee_bps);
75
80
  }
76
81
 
82
+ /// Sets or removes the fee rate for a specific destination endpoint.
83
+ ///
84
+ /// # Arguments
85
+ /// * `dst_eid` - The destination endpoint ID
86
+ /// * `fee_bps` - The fee rate (0-10,000), or None to remove the fee configuration
77
87
  #[only_auth]
78
- fn unset_fee_bps(env: &Env, dst_eid: u32) {
79
- assert_with_error!(env, OFTFeeStorage::has_fee_bps(env, dst_eid), OFTFeeError::NotFound);
80
- OFTFeeStorage::remove_fee_bps(env, dst_eid);
81
- FeeBpsUnset { dst_eid }.publish(env);
88
+ fn set_fee_bps(env: &soroban_sdk::Env, dst_eid: u32, fee_bps: Option<u64>) {
89
+ Self::__set_fee_bps(env, dst_eid, fee_bps);
82
90
  }
83
91
 
92
+ /// Sets the address where collected fees will be deposited.
84
93
  #[only_auth]
85
- fn set_fee_deposit_address(env: &Env, fee_deposit_address: Address) {
86
- if let Some(current_address) = OFTFeeStorage::fee_deposit_address(env) {
87
- assert_with_error!(env, current_address != fee_deposit_address, OFTFeeError::SameValue);
88
- }
89
- OFTFeeStorage::set_fee_deposit_address(env, &fee_deposit_address);
90
- FeeDepositAddressSet { fee_deposit_address }.publish(env);
94
+ fn set_fee_deposit_address(env: &soroban_sdk::Env, fee_deposit_address: soroban_sdk::Address) {
95
+ Self::__set_fee_deposit_address(env, &fee_deposit_address);
91
96
  }
92
97
 
93
- fn has_fee_bps(env: &Env, dst_eid: u32) -> bool {
94
- Self::effective_fee_bps(env, dst_eid) > 0
95
- }
98
+ // =========================================================================
99
+ // View Functions
100
+ // =========================================================================
96
101
 
97
- fn effective_fee_bps(env: &Env, dst_eid: u32) -> u64 {
98
- if OFTFeeStorage::has_fee_bps(env, dst_eid) {
99
- OFTFeeStorage::fee_bps(env, dst_eid).unwrap()
100
- } else {
101
- OFTFeeStorage::default_fee_bps(env)
102
- }
102
+ /// Returns the default fee rate in basis points.
103
+ fn default_fee_bps(env: &soroban_sdk::Env) -> u64 {
104
+ Self::__default_fee_bps(env)
103
105
  }
104
106
 
105
- fn default_fee_bps(env: &Env) -> u64 {
106
- OFTFeeStorage::default_fee_bps(env)
107
+ /// Returns the fee rate for a specific destination, if set.
108
+ fn fee_bps(env: &soroban_sdk::Env, dst_eid: u32) -> Option<u64> {
109
+ Self::__fee_bps(env, dst_eid)
107
110
  }
108
111
 
109
- fn fee_bps(env: &Env, dst_eid: u32) -> Option<u64> {
110
- OFTFeeStorage::fee_bps(env, dst_eid)
112
+ /// Returns the effective fee rate for a destination (destination-specific or default).
113
+ fn effective_fee_bps(env: &soroban_sdk::Env, dst_eid: u32) -> u64 {
114
+ Self::__effective_fee_bps(env, dst_eid)
111
115
  }
112
116
 
113
- fn fee_deposit_address(env: &Env) -> Address {
114
- OFTFeeStorage::fee_deposit_address(env).unwrap_or_panic(env, OFTFeeError::InvalidFeeDepositAddress)
117
+ /// Returns the fee deposit address.
118
+ fn fee_deposit_address(env: &soroban_sdk::Env) -> soroban_sdk::Address {
119
+ Self::__fee_deposit_address(env)
115
120
  }
116
121
  }
117
122
 
118
123
  /// Internal trait for OFT fee operations used by OFT hooks.
119
- /// Contains only truly internal methods that are called from OFTInner implementations.
124
+ /// Contains only truly internal methods that are called from OFTInternal implementations.
120
125
  pub trait OFTFeeInternal {
126
+ // =========================================================================
127
+ // OFT Hooks
128
+ // =========================================================================
129
+
121
130
  /// Calculates the fee amount for a given transfer (read-only).
122
131
  /// Used internally by `__debit_view` to calculate the fee.
123
132
  ///
@@ -128,40 +137,109 @@ pub trait OFTFeeInternal {
128
137
  /// # Returns
129
138
  /// The fee amount to be deducted
130
139
  fn __fee_view(env: &Env, dst_eid: u32, amount_ld: i128) -> i128 {
131
- // Calculate effective fee (destination-specific or default)
132
- let fee_bps = if OFTFeeStorage::has_fee_bps(env, dst_eid) {
133
- OFTFeeStorage::fee_bps(env, dst_eid).unwrap()
134
- } else {
135
- OFTFeeStorage::default_fee_bps(env)
136
- };
140
+ let fee_bps = Self::__effective_fee_bps(env, dst_eid);
137
141
  if fee_bps == 0 {
138
142
  return 0;
139
143
  }
144
+
140
145
  // Check that fee deposit address is set (required for fee collection)
141
- assert_with_error!(
142
- env,
143
- OFTFeeStorage::fee_deposit_address(env).is_some(),
144
- OFTFeeError::InvalidFeeDepositAddress
145
- );
146
+ assert_with_error!(env, OFTFeeStorage::has_fee_deposit_address(env), OFTFeeError::InvalidFeeDepositAddress);
147
+
146
148
  (amount_ld * fee_bps as i128) / BASE_FEE_BPS as i128
147
149
  }
148
150
 
149
- /// Charges the fee by transferring the fee amount from sender to the fee deposit address.
150
- /// Used internally by `__debit` to collect the fee (mirrors `__debit`).
151
+ /// Charges the fee by transferring the fee amount from the sender to the fee deposit address.
152
+ /// Used internally by `__debit` to collect the fee.
151
153
  ///
152
154
  /// # Arguments
153
155
  /// * `token` - The token address to transfer
154
- /// * `sender` - The sender address to transfer fee from
156
+ /// * `from` - The address to transfer fee from
155
157
  /// * `fee_amount` - The fee amount to transfer
156
- fn __charge_fee(env: &Env, token: &Address, sender: &Address, fee_amount: i128) {
158
+ fn __charge_fee(env: &Env, token: &Address, from: &Address, fee_amount: i128) {
157
159
  if fee_amount != 0 {
158
- assert_with_error!(
159
- env,
160
- OFTFeeStorage::fee_deposit_address(env).is_some(),
161
- OFTFeeError::InvalidFeeDepositAddress
162
- );
163
- let fee_deposit = OFTFeeStorage::fee_deposit_address(env).unwrap();
164
- TokenClient::new(env, token).transfer(sender, &fee_deposit, &fee_amount);
160
+ let fee_deposit = Self::__fee_deposit_address(env);
161
+ TokenClient::new(env, token).transfer(from, &fee_deposit, &fee_amount);
162
+ }
163
+ }
164
+
165
+ // =========================================================================
166
+ // Management Functions
167
+ // =========================================================================
168
+
169
+ /// Sets the default fee rate in basis points.
170
+ ///
171
+ /// # Arguments
172
+ /// * `default_fee_bps` - The default fee rate (0-10,000, where 10,000 = 100%)
173
+ fn __set_default_fee_bps(env: &Env, default_fee_bps: u64) {
174
+ assert_with_error!(env, default_fee_bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
175
+
176
+ let current_default = Self::__default_fee_bps(env);
177
+ assert_with_error!(env, current_default != default_fee_bps, OFTFeeError::SameValue);
178
+
179
+ OFTFeeStorage::set_default_fee_bps(env, &default_fee_bps);
180
+
181
+ DefaultFeeBpsSet { fee_bps: default_fee_bps }.publish(env);
182
+ }
183
+
184
+ /// Sets or removes the fee rate for a specific destination endpoint.
185
+ ///
186
+ /// # Arguments
187
+ /// * `dst_eid` - The destination endpoint ID
188
+ /// * `fee_bps` - The fee rate (0-10,000), or None to remove the fee configuration
189
+ fn __set_fee_bps(env: &Env, dst_eid: u32, fee_bps: Option<u64>) {
190
+ let current_fee_bps = Self::__fee_bps(env, dst_eid);
191
+ assert_with_error!(env, current_fee_bps != fee_bps, OFTFeeError::SameValue);
192
+
193
+ match fee_bps {
194
+ Some(bps) => {
195
+ assert_with_error!(env, bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
196
+ OFTFeeStorage::set_fee_bps(env, dst_eid, &bps);
197
+ }
198
+ None => {
199
+ OFTFeeStorage::remove_fee_bps(env, dst_eid);
200
+ }
201
+ }
202
+
203
+ FeeBpsSet { dst_eid, fee_bps }.publish(env);
204
+ }
205
+
206
+ /// Sets the address where collected fees will be deposited.
207
+ ///
208
+ /// # Arguments
209
+ /// * `fee_deposit_address` - The address to deposit fees to
210
+ fn __set_fee_deposit_address(env: &Env, fee_deposit_address: &Address) {
211
+ if let Some(current_address) = OFTFeeStorage::fee_deposit_address(env) {
212
+ assert_with_error!(env, current_address != *fee_deposit_address, OFTFeeError::SameValue);
213
+ }
214
+ OFTFeeStorage::set_fee_deposit_address(env, fee_deposit_address);
215
+ FeeDepositAddressSet { fee_deposit_address: fee_deposit_address.clone() }.publish(env);
216
+ }
217
+
218
+ // =========================================================================
219
+ // View Functions
220
+ // =========================================================================
221
+
222
+ /// Returns the effective fee rate for a destination (destination-specific or default).
223
+ fn __effective_fee_bps(env: &Env, dst_eid: u32) -> u64 {
224
+ if OFTFeeStorage::has_fee_bps(env, dst_eid) {
225
+ OFTFeeStorage::fee_bps(env, dst_eid).unwrap()
226
+ } else {
227
+ OFTFeeStorage::default_fee_bps(env)
165
228
  }
166
229
  }
230
+
231
+ /// Returns the default fee rate in basis points.
232
+ fn __default_fee_bps(env: &Env) -> u64 {
233
+ OFTFeeStorage::default_fee_bps(env)
234
+ }
235
+
236
+ /// Returns the fee rate for a specific destination, if set.
237
+ fn __fee_bps(env: &Env, dst_eid: u32) -> Option<u64> {
238
+ OFTFeeStorage::fee_bps(env, dst_eid)
239
+ }
240
+
241
+ /// Returns the fee deposit address.
242
+ fn __fee_deposit_address(env: &Env) -> Address {
243
+ OFTFeeStorage::fee_deposit_address(env).unwrap_or_panic(env, OFTFeeError::InvalidFeeDepositAddress)
244
+ }
167
245
  }