@layerzerolabs/protocol-stellar-v2 0.2.15 → 0.2.19

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 (262) hide show
  1. package/.turbo/turbo-build.log +365 -297
  2. package/.turbo/turbo-lint.log +142 -110
  3. package/.turbo/turbo-test.log +1273 -1222
  4. package/Cargo.lock +20 -5
  5. package/Cargo.toml +4 -1
  6. package/contracts/ERROR_SPEC.md +44 -0
  7. package/contracts/common-macros/src/auth.rs +113 -0
  8. package/contracts/common-macros/src/contract_ttl.rs +84 -0
  9. package/contracts/common-macros/src/lib.rs +181 -30
  10. package/contracts/common-macros/src/lz_contract.rs +83 -0
  11. package/contracts/common-macros/src/tests/{ownable.rs → auth.rs} +48 -15
  12. package/contracts/common-macros/src/tests/contract_ttl.rs +662 -0
  13. package/contracts/common-macros/src/tests/mod.rs +2 -2
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +20 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +24 -0
  16. package/contracts/common-macros/src/tests/snapshots/{common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap → common_macros__tests__auth__snapshot_only_auth_preserves_function_signature.snap} +4 -4
  17. package/contracts/common-macros/src/tests/snapshots/{common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap → common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap} +3 -3
  18. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contracttrait_code.snap +69 -0
  19. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +7 -21
  20. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +2 -2
  21. package/contracts/common-macros/src/ttl_configurable.rs +19 -34
  22. package/contracts/common-macros/src/ttl_extendable.rs +36 -0
  23. package/contracts/common-macros/src/upgradeable.rs +5 -5
  24. package/contracts/common-macros/src/utils.rs +9 -0
  25. package/contracts/endpoint-v2/src/constants.rs +4 -4
  26. package/contracts/endpoint-v2/src/endpoint_v2.rs +38 -40
  27. package/contracts/endpoint-v2/src/errors.rs +4 -3
  28. package/contracts/endpoint-v2/src/events.rs +1 -1
  29. package/contracts/endpoint-v2/src/message_lib_manager.rs +18 -5
  30. package/contracts/endpoint-v2/src/messaging_channel.rs +11 -1
  31. package/contracts/endpoint-v2/src/messaging_composer.rs +11 -1
  32. package/contracts/endpoint-v2/src/storage.rs +1 -1
  33. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +3 -3
  34. package/contracts/endpoint-v2/src/tests/endpoint_v2/quote.rs +1 -1
  35. package/contracts/endpoint-v2/src/tests/endpoint_v2/require_oapp_auth.rs +2 -2
  36. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +3 -3
  37. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
  38. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_receive_lib_for_eid.rs +3 -3
  39. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_registered.rs +1 -1
  40. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_send_lib_for_eid.rs +3 -3
  41. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_supported_eid.rs +1 -1
  42. package/contracts/endpoint-v2/src/tests/messaging_channel/clear_payload.rs +4 -4
  43. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound.rs +1 -1
  44. package/contracts/layerzero-views/src/layerzero_view.rs +3 -6
  45. package/contracts/macro-integration-tests/tests/runtime/ownable/mod.rs +2 -2
  46. package/contracts/macro-integration-tests/tests/runtime/ownable/{only_owner_guard.rs → only_auth_guard.rs} +1 -1
  47. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/configuration.rs +1 -1
  48. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/freeze.rs +1 -1
  49. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/mod.rs +0 -1
  50. package/contracts/macro-integration-tests/tests/ui/ownable/fail/{only_owner_missing_env.rs → only_auth_missing_env.rs} +3 -3
  51. package/contracts/macro-integration-tests/tests/ui/ownable/fail/{only_owner_missing_env.stderr → only_auth_missing_env.stderr} +4 -4
  52. package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +2 -3
  53. package/contracts/macro-integration-tests/tests/ui/ownable/pass/{only_owner_env_param_variants.rs → only_auth_env_param_variants.rs} +9 -9
  54. package/contracts/macro-integration-tests/tests/ui/ttl_configurable/pass/minimal_contract.rs +6 -6
  55. package/contracts/message-libs/message-lib-common/src/errors.rs +7 -2
  56. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1/decode_packet_header.rs +3 -3
  57. package/contracts/message-libs/message-lib-common/src/tests/worker_options/append_lz_receive_option.rs +1 -2
  58. package/contracts/message-libs/message-lib-common/src/tests/worker_options/append_native_drop_option.rs +1 -2
  59. package/contracts/message-libs/message-lib-common/src/tests/worker_options/convert_legacy_options.rs +9 -9
  60. package/contracts/message-libs/message-lib-common/src/tests/worker_options/extract_type_3_options.rs +1 -1
  61. package/contracts/message-libs/message-lib-common/src/tests/worker_options/left_pad_to_bytes32.rs +1 -1
  62. package/contracts/message-libs/message-lib-common/src/tests/worker_options/split_worker_options.rs +2 -2
  63. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +7 -9
  64. package/contracts/message-libs/treasury/src/errors.rs +2 -2
  65. package/contracts/message-libs/treasury/src/events.rs +1 -1
  66. package/contracts/message-libs/treasury/src/interfaces/zro_fee_lib.rs +2 -2
  67. package/contracts/message-libs/treasury/src/storage.rs +1 -1
  68. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +1 -1
  69. package/contracts/message-libs/treasury/src/treasury.rs +14 -16
  70. package/contracts/message-libs/uln-302/src/receive_uln.rs +13 -2
  71. package/contracts/message-libs/uln-302/src/send_uln.rs +24 -4
  72. package/contracts/message-libs/uln-302/src/uln302.rs +6 -24
  73. package/contracts/oapps/counter/Cargo.toml +14 -1
  74. package/contracts/oapps/counter/integration_tests/mod.rs +4 -1
  75. package/contracts/oapps/counter/integration_tests/{setup.rs → setup_sml.rs} +48 -80
  76. package/contracts/oapps/counter/integration_tests/setup_uln.rs +997 -0
  77. package/contracts/oapps/counter/integration_tests/signing.rs +62 -0
  78. package/contracts/oapps/counter/integration_tests/test_with_sml.rs +24 -55
  79. package/contracts/oapps/counter/integration_tests/test_with_uln.rs +314 -0
  80. package/contracts/oapps/counter/integration_tests/utils.rs +196 -53
  81. package/contracts/oapps/counter/src/counter.rs +67 -43
  82. package/contracts/oapps/counter/src/tests/mod.rs +0 -13
  83. package/contracts/oapps/counter/src/tests/test_counter.rs +5 -7
  84. package/contracts/oapps/oapp/src/errors.rs +5 -1
  85. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +93 -78
  86. package/contracts/oapps/oapp/src/oapp_core.rs +36 -21
  87. package/contracts/oapps/oapp/src/oapp_options_type3.rs +48 -12
  88. package/contracts/oapps/oapp/src/oapp_receiver.rs +106 -41
  89. package/contracts/oapps/oapp/src/oapp_sender.rs +26 -34
  90. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +9 -8
  91. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +25 -17
  92. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +7 -7
  93. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +14 -15
  94. package/contracts/oapps/oapp-macros/src/generators.rs +128 -0
  95. package/contracts/oapps/oapp-macros/src/lib.rs +113 -56
  96. package/contracts/oapps/oft/Cargo.toml +10 -7
  97. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_oft_fee.rs +3 -4
  98. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_pausable.rs +2 -3
  99. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_rate_limiter.rs +1 -1
  100. package/contracts/oapps/oft/integration-tests/mod.rs +1 -1
  101. package/contracts/oapps/oft/integration-tests/setup.rs +29 -110
  102. package/contracts/oapps/oft/integration-tests/utils.rs +254 -21
  103. package/contracts/oapps/oft/src/extensions/oft_fee.rs +13 -14
  104. package/contracts/oapps/oft/src/extensions/pausable.rs +4 -4
  105. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +5 -5
  106. package/contracts/oapps/oft/src/lib.rs +11 -13
  107. package/contracts/oapps/oft/src/oft.rs +147 -225
  108. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +9 -13
  109. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +31 -14
  110. package/contracts/oapps/oft/src/oft_types/mod.rs +13 -0
  111. package/contracts/oapps/{oft-std → oft-core}/Cargo.toml +6 -4
  112. package/contracts/oapps/{oft-std → oft-core}/integration-tests/mod.rs +1 -1
  113. package/contracts/oapps/{oft-std → oft-core}/integration-tests/setup.rs +129 -30
  114. package/contracts/oapps/{oft → oft-core}/integration-tests/test_with_sml.rs +3 -3
  115. package/contracts/oapps/oft-core/integration-tests/utils.rs +201 -0
  116. package/contracts/oapps/oft-core/src/errors.rs +13 -0
  117. package/contracts/oapps/oft-core/src/lib.rs +18 -0
  118. package/contracts/oapps/oft-core/src/oft_core.rs +439 -0
  119. package/contracts/oapps/{oft → oft-core}/src/storage.rs +2 -0
  120. package/contracts/oapps/{oft → oft-core}/src/tests/mod.rs +0 -2
  121. package/contracts/oapps/{oft → oft-core}/src/tests/test_decimals.rs +2 -2
  122. package/contracts/oapps/{oft → oft-core}/src/tests/test_lz_receive.rs +7 -7
  123. package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_msg_codec.rs +4 -5
  124. package/contracts/oapps/{oft → oft-core}/src/tests/test_resolve_address.rs +3 -3
  125. package/contracts/oapps/{oft → oft-core}/src/tests/test_utils.rs +78 -37
  126. package/contracts/oapps/oft-core/src/types.rs +58 -0
  127. package/contracts/oapps/{oft → oft-core}/src/utils.rs +1 -1
  128. package/contracts/upgrader/src/lib.rs +4 -4
  129. package/contracts/utils/src/auth.rs +44 -0
  130. package/contracts/utils/src/errors.rs +31 -5
  131. package/contracts/utils/src/lib.rs +3 -0
  132. package/contracts/utils/src/multisig.rs +211 -0
  133. package/contracts/utils/src/ownable.rs +137 -13
  134. package/contracts/utils/src/tests/buffer_reader.rs +6 -6
  135. package/contracts/utils/src/tests/buffer_writer.rs +6 -6
  136. package/contracts/utils/src/tests/bytes_ext.rs +2 -4
  137. package/contracts/utils/src/tests/mod.rs +1 -0
  138. package/contracts/utils/src/tests/multisig.rs +731 -0
  139. package/contracts/utils/src/tests/option_ext.rs +2 -5
  140. package/contracts/utils/src/tests/ownable.rs +456 -7
  141. package/contracts/utils/src/tests/ttl_configurable.rs +27 -16
  142. package/contracts/utils/src/tests/upgradeable.rs +4 -2
  143. package/contracts/utils/src/ttl_configurable.rs +23 -8
  144. package/contracts/utils/src/ttl_extendable.rs +27 -0
  145. package/contracts/utils/src/upgradeable.rs +2 -0
  146. package/contracts/workers/dvn/Cargo.toml +1 -1
  147. package/contracts/workers/dvn/src/auth.rs +7 -7
  148. package/contracts/workers/dvn/src/dvn.rs +10 -38
  149. package/contracts/workers/dvn/src/errors.rs +0 -7
  150. package/contracts/workers/dvn/src/events.rs +1 -14
  151. package/contracts/workers/dvn/src/interfaces/dvn.rs +2 -2
  152. package/contracts/workers/dvn/src/interfaces/mod.rs +0 -2
  153. package/contracts/workers/dvn/src/storage.rs +3 -13
  154. package/contracts/workers/dvn/src/tests/auth.rs +4 -4
  155. package/contracts/workers/dvn/src/tests/dvn.rs +1 -2
  156. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +7 -8
  157. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +11 -8
  158. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +11 -12
  159. package/contracts/workers/dvn/src/tests/setup.rs +5 -5
  160. package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
  161. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +3 -6
  162. package/contracts/workers/executor/src/auth.rs +80 -16
  163. package/contracts/workers/executor/src/executor.rs +5 -31
  164. package/contracts/workers/executor/src/storage.rs +2 -9
  165. package/contracts/workers/executor-fee-lib/Cargo.toml +1 -1
  166. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +3 -6
  167. package/contracts/workers/executor-helper/Cargo.toml +1 -1
  168. package/contracts/workers/executor-helper/src/executor_helper.rs +53 -73
  169. package/contracts/workers/price-feed/Cargo.toml +1 -1
  170. package/contracts/workers/price-feed/src/price_feed.rs +7 -10
  171. package/contracts/workers/worker/src/errors.rs +4 -0
  172. package/contracts/workers/worker/src/tests/worker.rs +7 -6
  173. package/contracts/workers/worker/src/worker.rs +20 -16
  174. package/package.json +7 -5
  175. package/sdk/.turbo/turbo-build.log +1 -0
  176. package/sdk/.turbo/turbo-test.log +1019 -0
  177. package/sdk/dist/generated/bml.d.ts +95 -8
  178. package/sdk/dist/generated/bml.js +95 -36
  179. package/sdk/dist/generated/counter.d.ts +289 -44
  180. package/sdk/dist/generated/counter.js +119 -49
  181. package/sdk/dist/generated/dvn.d.ts +312 -229
  182. package/sdk/dist/generated/dvn.js +144 -83
  183. package/sdk/dist/generated/dvn_fee_lib.d.ts +258 -63
  184. package/sdk/dist/generated/dvn_fee_lib.js +95 -26
  185. package/sdk/dist/generated/endpoint.d.ts +219 -24
  186. package/sdk/dist/generated/endpoint.js +108 -41
  187. package/sdk/dist/generated/executor.d.ts +239 -87
  188. package/sdk/dist/generated/executor.js +135 -63
  189. package/sdk/dist/generated/executor_fee_lib.d.ts +278 -74
  190. package/sdk/dist/generated/executor_fee_lib.js +135 -59
  191. package/sdk/dist/generated/executor_helper.d.ts +163 -21
  192. package/sdk/dist/generated/executor_helper.js +124 -52
  193. package/sdk/dist/generated/oft.d.ts +1842 -0
  194. package/sdk/dist/generated/oft.js +345 -0
  195. package/sdk/dist/generated/price_feed.d.ts +258 -63
  196. package/sdk/dist/generated/price_feed.js +95 -26
  197. package/sdk/dist/generated/sml.d.ts +235 -34
  198. package/sdk/dist/generated/sml.js +126 -53
  199. package/sdk/dist/generated/treasury.d.ts +1016 -0
  200. package/sdk/dist/generated/treasury.js +248 -0
  201. package/sdk/dist/generated/uln302.d.ts +235 -34
  202. package/sdk/dist/generated/uln302.js +126 -53
  203. package/sdk/dist/generated/upgrader.d.ts +17 -2
  204. package/sdk/dist/generated/upgrader.js +19 -1
  205. package/sdk/dist/index.d.ts +2 -1
  206. package/sdk/dist/index.js +2 -1
  207. package/sdk/package.json +6 -3
  208. package/sdk/src/index.ts +2 -1
  209. package/sdk/test/counter-sml.test.ts +376 -0
  210. package/sdk/test/counter-uln.test.ts +493 -0
  211. package/sdk/test/{oft.test.ts → oft-sml.test.ts} +196 -321
  212. package/sdk/test/suites/constants.ts +22 -2
  213. package/sdk/test/suites/globalSetup.ts +450 -0
  214. package/sdk/test/suites/localnet.ts +23 -6
  215. package/sdk/test/upgrader.test.ts +7 -16
  216. package/sdk/test/utils.ts +558 -85
  217. package/sdk/turbo.json +8 -0
  218. package/sdk/vitest.config.ts +21 -0
  219. package/tools/ts-bindings-gen/Cargo.toml +2 -0
  220. package/tools/ts-bindings-gen/src/main.rs +52 -4
  221. package/contracts/common-macros/src/contract_impl.rs +0 -52
  222. package/contracts/common-macros/src/ownable.rs +0 -41
  223. package/contracts/common-macros/src/tests/contract_impl.rs +0 -386
  224. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +0 -12
  225. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/extend_instance_ttl.rs +0 -50
  226. package/contracts/oapps/oapp-macros/src/oapp_core.rs +0 -41
  227. package/contracts/oapps/oapp-macros/src/oapp_full.rs +0 -21
  228. package/contracts/oapps/oapp-macros/src/oapp_options_type3.rs +0 -31
  229. package/contracts/oapps/oapp-macros/src/oapp_receiver.rs +0 -48
  230. package/contracts/oapps/oapp-macros/src/oapp_sender.rs +0 -21
  231. package/contracts/oapps/oapp-macros/src/util.rs +0 -107
  232. package/contracts/oapps/oft/src/constants.rs +0 -5
  233. package/contracts/oapps/oft/src/default_oft_impl.rs +0 -152
  234. package/contracts/oapps/oft/src/errors.rs +0 -8
  235. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +0 -23
  236. package/contracts/oapps/oft/src/interfaces/mod.rs +0 -3
  237. package/contracts/oapps/oft/src/tests/extensions/mod.rs +0 -11
  238. package/contracts/oapps/oft/src/tests/extensions/setup.rs +0 -903
  239. package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +0 -749
  240. package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +0 -432
  241. package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +0 -1078
  242. package/contracts/oapps/oft/src/types.rs +0 -38
  243. package/contracts/oapps/oft-std/integration-tests/utils.rs +0 -427
  244. package/contracts/oapps/oft-std/src/lib.rs +0 -16
  245. package/contracts/oapps/oft-std/src/oft.rs +0 -156
  246. package/contracts/workers/dvn/src/interfaces/multisig.rs +0 -56
  247. package/contracts/workers/dvn/src/multisig.rs +0 -157
  248. package/sdk/dist/generated/oft_std.d.ts +0 -1544
  249. package/sdk/dist/generated/oft_std.js +0 -271
  250. package/sdk/test/index.test.ts +0 -375
  251. /package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/mod.rs +0 -0
  252. /package/contracts/oapps/{oft → oft-core}/src/codec/mod.rs +0 -0
  253. /package/contracts/oapps/{oft → oft-core}/src/codec/oft_compose_msg_codec.rs +0 -0
  254. /package/contracts/oapps/{oft → oft-core}/src/codec/oft_msg_codec.rs +0 -0
  255. /package/contracts/oapps/{oft → oft-core}/src/events.rs +0 -0
  256. /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_compose_msg_codec.rs +0 -0
  257. /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_version.rs +0 -0
  258. /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_oft.rs +0 -0
  259. /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_send.rs +0 -0
  260. /package/contracts/oapps/{oft → oft-core}/src/tests/test_send.rs +0 -0
  261. /package/contracts/oapps/{oft → oft-core}/src/tests/test_token.rs +0 -0
  262. /package/sdk/test/suites/{testUpgradeable.ts → dummyContractClient.ts} +0 -0
@@ -1,903 +0,0 @@
1
- //! Test setup for ExtensiveOFT with all extensions (pausable, oft_fee, rate_limiter).
2
- //!
3
- //! This module provides a comprehensive test setup similar to `test_utils.rs` but
4
- //! specifically for testing ExtensiveOFT with extension functionality.
5
-
6
- extern crate self as oft;
7
-
8
- use crate::default_oft_impl::{default_quote_oft, default_quote_send};
9
- use crate::errors::OFTError;
10
- use crate::extensions::oft_fee::{OFTFee, OFTFeeInternal};
11
- use crate::extensions::pausable::{OFTPausable, OFTPausableInternal};
12
- use crate::extensions::rate_limiter::{Direction, RateLimiter, RateLimiterInternal};
13
- use crate::oft::{oft_initialize, OFTInternal, OFT};
14
- use crate::storage::OFTStorage;
15
- use crate::tests::test_utils::{
16
- create_recipient_address, DummyToken, MockEndpointWithCompose, MockEndpointWithComposeClient, DEFAULT_NATIVE_FEE,
17
- DEFAULT_SHARED_DECIMALS, DEFAULT_ZRO_FEE, INITIAL_MINT_AMOUNT,
18
- };
19
- use crate::types::{OFTFeeDetail, OFTLimit, OFTReceipt, SendParam};
20
- use crate::utils::remove_dust;
21
- use endpoint_v2::{LayerZeroReceiverClient, MessagingFee, MessagingReceipt, Origin};
22
- use oapp::oapp_core::OAppCoreClient;
23
- use soroban_sdk::{
24
- assert_with_error, bytes, contractimpl, log,
25
- testutils::{Ledger, MockAuth, MockAuthInvoke},
26
- token::{StellarAssetClient, TokenClient},
27
- Address, Bytes, BytesN, Env, IntoVal,
28
- };
29
-
30
- // ==================== ExtensiveOFT Contract ====================
31
-
32
- /// OFT contract with all three extensions enabled: pausable, oft_fee, rate_limiter.
33
- #[oapp_macros::oapp]
34
- pub struct ExtensiveOFT;
35
-
36
- #[contractimpl]
37
- impl ExtensiveOFT {
38
- pub fn __constructor(
39
- env: &Env,
40
- token: &Address,
41
- owner: &Address,
42
- endpoint: &Address,
43
- delegate: &Option<Address>,
44
- shared_decimals: u32,
45
- ) {
46
- oft_initialize::<Self>(env, owner, token, endpoint, delegate, shared_decimals);
47
- }
48
- }
49
-
50
- // Implement OFT trait with custom overrides for extensions
51
- #[contractimpl(contracttrait)]
52
- impl OFT for ExtensiveOFT {
53
- fn quote_oft(
54
- env: &Env,
55
- send_param: &crate::types::SendParam,
56
- ) -> (OFTLimit, soroban_sdk::Vec<OFTFeeDetail>, OFTReceipt) {
57
- Self::__assert_not_paused(env);
58
- let (_, fee_details, oft_receipt) = default_quote_oft::<Self>(env, send_param);
59
- let capacity = Self::rate_limit_capacity(env, &Direction::Outbound, send_param.dst_eid);
60
- let oft_limit = OFTLimit { min_amount_ld: 0, max_amount_ld: capacity };
61
- (oft_limit, fee_details, oft_receipt)
62
- }
63
-
64
- fn quote_send(
65
- env: &Env,
66
- sender: &Address,
67
- send_param: &crate::types::SendParam,
68
- pay_in_zro: bool,
69
- ) -> endpoint_v2::MessagingFee {
70
- Self::__assert_not_paused(env);
71
- default_quote_send::<Self>(env, sender, send_param, pay_in_zro)
72
- }
73
- }
74
-
75
- // Internal OFT implementation - NOT exposed as contract endpoints
76
- impl OFTInternal for ExtensiveOFT {
77
- fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
78
- // 1. Pausable check
79
- Self::__assert_not_paused(env);
80
-
81
- // 2. Core debit logic
82
- let oft_receipt = crate::oft_types::mint_burn::debit::<Self>(env, sender, amount_ld, min_amount_ld, dst_eid);
83
-
84
- // 3. Rate limit checks
85
- Self::__consume_rate_limit_capacity(env, &Direction::Outbound, dst_eid, oft_receipt.amount_received_ld);
86
- Self::__release_rate_limit_capacity(env, &Direction::Inbound, dst_eid, oft_receipt.amount_received_ld);
87
-
88
- // 4. Charge fee
89
- Self::__charge_fee(
90
- env,
91
- &Self::token(env),
92
- sender,
93
- oft_receipt.amount_sent_ld - oft_receipt.amount_received_ld,
94
- );
95
-
96
- oft_receipt
97
- }
98
-
99
- fn __credit(env: &Env, to: &Address, amount_ld: i128, src_eid: u32) -> i128 {
100
- // 1. Pausable check
101
- Self::__assert_not_paused(env);
102
-
103
- // 2. Core credit logic
104
- let amount_credited = crate::oft_types::mint_burn::credit::<Self>(env, to, amount_ld, src_eid);
105
-
106
- // 3. Rate limit checks
107
- Self::__consume_rate_limit_capacity(env, &Direction::Inbound, src_eid, amount_credited);
108
- Self::__release_rate_limit_capacity(env, &Direction::Outbound, src_eid, amount_credited);
109
-
110
- amount_credited
111
- }
112
-
113
- fn __debit_view(env: &Env, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
114
- let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
115
- let amount_after_fee = Self::__fee_view(env, dst_eid, amount_ld);
116
- let amount_received_ld = remove_dust(amount_after_fee, conversion_rate);
117
- // Note: when no fee is applied, amount_send_ld is equal to amount_received_ld
118
- // this is to align the behavior with the fee extensions on other VMs
119
- let amount_sent_ld = if amount_after_fee == amount_ld { amount_received_ld } else { amount_ld };
120
- assert_with_error!(env, amount_received_ld >= min_amount_ld, OFTError::SlippageExceeded);
121
-
122
- OFTReceipt { amount_sent_ld, amount_received_ld }
123
- }
124
- }
125
-
126
- // Extension traits - exposed as contract endpoints
127
- #[contractimpl(contracttrait)]
128
- impl OFTFee for ExtensiveOFT {}
129
-
130
- impl OFTFeeInternal for ExtensiveOFT {}
131
-
132
- #[contractimpl(contracttrait)]
133
- impl OFTPausable for ExtensiveOFT {}
134
-
135
- impl OFTPausableInternal for ExtensiveOFT {}
136
-
137
- #[contractimpl(contracttrait)]
138
- impl RateLimiter for ExtensiveOFT {}
139
-
140
- impl RateLimiterInternal for ExtensiveOFT {}
141
-
142
- // ==================== ExtensiveOFT Test Setup ====================
143
-
144
- /// Test setup for ExtensiveOFT with all three extensions enabled.
145
- pub struct ExtensiveOFTTestSetup<'a> {
146
- pub env: &'a Env,
147
- pub oft: ExtensiveOFTClient<'a>,
148
- pub endpoint_client: MockEndpointWithComposeClient<'a>,
149
- pub token: Address,
150
- pub token_client: TokenClient<'a>,
151
- pub native_token: Address,
152
- pub zro_token: Address,
153
- pub owner: Address,
154
- pub fee_collector: Address,
155
- pub native_fee: i128,
156
- pub zro_fee: i128,
157
- pub token_decimals: u32,
158
- pub shared_decimals: u32,
159
- }
160
-
161
- /// Builder for ExtensiveOFTTestSetup
162
- pub struct ExtensiveOFTTestSetupBuilder<'a> {
163
- env: &'a Env,
164
- native_fee: i128,
165
- zro_fee: i128,
166
- token_decimals: u32,
167
- shared_decimals: u32,
168
- }
169
-
170
- impl<'a> ExtensiveOFTTestSetupBuilder<'a> {
171
- pub fn new(env: &'a Env) -> Self {
172
- Self {
173
- env,
174
- native_fee: DEFAULT_NATIVE_FEE,
175
- zro_fee: DEFAULT_ZRO_FEE,
176
- token_decimals: 7,
177
- shared_decimals: DEFAULT_SHARED_DECIMALS,
178
- }
179
- }
180
-
181
- pub fn with_token_decimals(mut self, decimals: u32) -> Self {
182
- self.token_decimals = decimals;
183
- self
184
- }
185
-
186
- pub fn with_shared_decimals(mut self, decimals: u32) -> Self {
187
- self.shared_decimals = decimals;
188
- self
189
- }
190
-
191
- pub fn with_fees(mut self, native_fee: i128, zro_fee: i128) -> Self {
192
- self.native_fee = native_fee;
193
- self.zro_fee = zro_fee;
194
- self
195
- }
196
-
197
- pub fn build(self) -> ExtensiveOFTTestSetup<'a> {
198
- let env = self.env;
199
- let native_fee = self.native_fee;
200
- let zro_fee = self.zro_fee;
201
-
202
- let owner = create_recipient_address(env);
203
- let fee_collector = create_recipient_address(env);
204
-
205
- // Create native token for fees
206
- let native_sac = env.register_stellar_asset_contract_v2(owner.clone());
207
- let native_token = native_sac.address();
208
-
209
- // Create ZRO token
210
- let zro_sac = env.register_stellar_asset_contract_v2(owner.clone());
211
- let zro_token = zro_sac.address();
212
-
213
- // Create OFT token (DummyToken with mint/burn capabilities)
214
- let token = env.register(DummyToken, (&owner, self.token_decimals));
215
- let token_client = TokenClient::new(env, &token);
216
-
217
- // Register mock endpoint
218
- let endpoint_address =
219
- env.register(MockEndpointWithCompose, (&native_fee, &zro_fee, &native_token, &zro_token));
220
- let endpoint_client = MockEndpointWithComposeClient::new(env, &endpoint_address);
221
-
222
- // Register ExtensiveOFT
223
- let delegate: Option<Address> = Some(owner.clone());
224
- let shared_decimals = self.shared_decimals;
225
- let oft_address = env.register(ExtensiveOFT, (&token, &owner, &endpoint_address, &delegate, &shared_decimals));
226
- let oft = ExtensiveOFTClient::new(env, &oft_address);
227
-
228
- // Pre-mint large amounts to owner
229
- ExtensiveOFTTestSetup::mint_to(env, &owner, &token, &owner, INITIAL_MINT_AMOUNT);
230
- ExtensiveOFTTestSetup::mint_to(env, &owner, &native_token, &owner, INITIAL_MINT_AMOUNT);
231
- ExtensiveOFTTestSetup::mint_to(env, &owner, &zro_token, &owner, INITIAL_MINT_AMOUNT);
232
-
233
- // Transfer token ownership to OFT so it can mint/burn tokens
234
- ExtensiveOFTTestSetup::transfer_token_ownership(env, &owner, &token, &oft_address);
235
-
236
- log!(&env, "token decimals: {}", self.token_decimals);
237
- log!(&env, "token address: {}", token);
238
- log!(&env, "native token address: {}", native_token);
239
- log!(&env, "zro token address: {}", zro_token);
240
- log!(&env, "owner: {}", owner);
241
- log!(&env, "fee_collector: {}", fee_collector);
242
- log!(&env, "native fee: {}", native_fee);
243
- log!(&env, "zro fee: {}", zro_fee);
244
- log!(&env, "oft address: {}", oft_address);
245
-
246
- ExtensiveOFTTestSetup {
247
- env,
248
- oft,
249
- endpoint_client,
250
- token,
251
- token_client,
252
- native_token,
253
- zro_token,
254
- owner,
255
- fee_collector,
256
- native_fee,
257
- zro_fee,
258
- token_decimals: self.token_decimals,
259
- shared_decimals: self.shared_decimals,
260
- }
261
- }
262
- }
263
-
264
- impl<'a> ExtensiveOFTTestSetup<'a> {
265
- /// Create a new test setup with default configuration
266
- pub fn new(env: &'a Env) -> Self {
267
- ExtensiveOFTTestSetupBuilder::new(env).build()
268
- }
269
-
270
- /// Create a builder for customized test setup
271
- pub fn builder(env: &'a Env) -> ExtensiveOFTTestSetupBuilder<'a> {
272
- ExtensiveOFTTestSetupBuilder::new(env)
273
- }
274
-
275
- // ==================== Token Helpers ====================
276
-
277
- pub fn mint_to(env: &Env, owner: &Address, token: &Address, to: &Address, amount: i128) {
278
- env.mock_auths(&[MockAuth {
279
- address: owner,
280
- invoke: &MockAuthInvoke {
281
- contract: token,
282
- fn_name: "mint",
283
- args: (to, amount).into_val(env),
284
- sub_invokes: &[],
285
- },
286
- }]);
287
- StellarAssetClient::new(env, token).mint(to, &amount);
288
- }
289
-
290
- pub fn transfer_token_ownership(env: &Env, owner: &Address, token: &Address, new_admin: &Address) {
291
- env.mock_auths(&[MockAuth {
292
- address: owner,
293
- invoke: &MockAuthInvoke {
294
- contract: token,
295
- fn_name: "set_admin",
296
- args: (new_admin,).into_val(env),
297
- sub_invokes: &[],
298
- },
299
- }]);
300
- StellarAssetClient::new(env, token).set_admin(new_admin);
301
- }
302
-
303
- /// Fund an account with native fees (transfers from owner)
304
- pub fn fund_native_fees(&self, to: &Address, amount: i128) {
305
- self.env.mock_auths(&[MockAuth {
306
- address: &self.owner,
307
- invoke: &MockAuthInvoke {
308
- contract: &self.native_token,
309
- fn_name: "transfer",
310
- args: (&self.owner, to, amount).into_val(self.env),
311
- sub_invokes: &[],
312
- },
313
- }]);
314
- TokenClient::new(self.env, &self.native_token).transfer(&self.owner, to, &amount);
315
- }
316
-
317
- /// Fund an account with ZRO fees (transfers from owner)
318
- pub fn fund_zro_fees(&self, to: &Address, amount: i128) {
319
- self.env.mock_auths(&[MockAuth {
320
- address: &self.owner,
321
- invoke: &MockAuthInvoke {
322
- contract: &self.zro_token,
323
- fn_name: "transfer",
324
- args: (&self.owner, to, amount).into_val(self.env),
325
- sub_invokes: &[],
326
- },
327
- }]);
328
- TokenClient::new(self.env, &self.zro_token).transfer(&self.owner, to, &amount);
329
- }
330
-
331
- /// Fund an account with OFT tokens (transfers from owner)
332
- pub fn fund_tokens(&self, to: &Address, amount: i128) {
333
- self.env.mock_auths(&[MockAuth {
334
- address: &self.owner,
335
- invoke: &MockAuthInvoke {
336
- contract: &self.token,
337
- fn_name: "transfer",
338
- args: (&self.owner, to, amount).into_val(self.env),
339
- sub_invokes: &[],
340
- },
341
- }]);
342
- self.token_client.transfer(&self.owner, to, &amount);
343
- }
344
-
345
- // ==================== OApp Helpers ====================
346
-
347
- pub fn set_peer(&self, eid: u32, peer: &BytesN<32>) {
348
- self.env.mock_auths(&[MockAuth {
349
- address: &self.owner,
350
- invoke: &MockAuthInvoke {
351
- contract: &self.oft.address,
352
- fn_name: "set_peer",
353
- args: (&eid, peer).into_val(self.env),
354
- sub_invokes: &[],
355
- },
356
- }]);
357
- OAppCoreClient::new(self.env, &self.oft.address).set_peer(&eid, &Some(peer.clone()));
358
- }
359
-
360
- // ==================== Pausable Extension Helpers ====================
361
-
362
- /// Set the paused state (owner only)
363
- pub fn set_paused(&self, paused: bool) {
364
- self.env.mock_auths(&[MockAuth {
365
- address: &self.owner,
366
- invoke: &MockAuthInvoke {
367
- contract: &self.oft.address,
368
- fn_name: "set_paused",
369
- args: (paused,).into_val(self.env),
370
- sub_invokes: &[],
371
- },
372
- }]);
373
- self.oft.set_paused(&paused);
374
- }
375
-
376
- /// Try to set paused state (returns Result)
377
- pub fn try_set_paused(
378
- &self,
379
- paused: bool,
380
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
381
- self.env.mock_auths(&[MockAuth {
382
- address: &self.owner,
383
- invoke: &MockAuthInvoke {
384
- contract: &self.oft.address,
385
- fn_name: "set_paused",
386
- args: (paused,).into_val(self.env),
387
- sub_invokes: &[],
388
- },
389
- }]);
390
- self.oft.try_set_paused(&paused)
391
- }
392
-
393
- /// Check if paused
394
- pub fn is_paused(&self) -> bool {
395
- self.oft.is_paused()
396
- }
397
-
398
- // ==================== OFT Fee Extension Helpers ====================
399
-
400
- /// Set the default fee in basis points (owner only)
401
- pub fn set_default_fee_bps(&self, fee_bps: u64) {
402
- self.env.mock_auths(&[MockAuth {
403
- address: &self.owner,
404
- invoke: &MockAuthInvoke {
405
- contract: &self.oft.address,
406
- fn_name: "set_default_fee_bps",
407
- args: (fee_bps,).into_val(self.env),
408
- sub_invokes: &[],
409
- },
410
- }]);
411
- self.oft.set_default_fee_bps(&fee_bps);
412
- }
413
-
414
- /// Try to set default fee bps (returns Result)
415
- pub fn try_set_default_fee_bps(
416
- &self,
417
- fee_bps: u64,
418
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
419
- self.env.mock_auths(&[MockAuth {
420
- address: &self.owner,
421
- invoke: &MockAuthInvoke {
422
- contract: &self.oft.address,
423
- fn_name: "set_default_fee_bps",
424
- args: (fee_bps,).into_val(self.env),
425
- sub_invokes: &[],
426
- },
427
- }]);
428
- self.oft.try_set_default_fee_bps(&fee_bps)
429
- }
430
-
431
- /// Set fee bps for a specific destination (owner only)
432
- pub fn set_fee_bps(&self, dst_eid: u32, fee_bps: u64) {
433
- self.env.mock_auths(&[MockAuth {
434
- address: &self.owner,
435
- invoke: &MockAuthInvoke {
436
- contract: &self.oft.address,
437
- fn_name: "set_fee_bps",
438
- args: (dst_eid, fee_bps).into_val(self.env),
439
- sub_invokes: &[],
440
- },
441
- }]);
442
- self.oft.set_fee_bps(&dst_eid, &fee_bps);
443
- }
444
-
445
- /// Try to set fee bps (returns Result)
446
- pub fn try_set_fee_bps(
447
- &self,
448
- dst_eid: u32,
449
- fee_bps: u64,
450
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
451
- self.env.mock_auths(&[MockAuth {
452
- address: &self.owner,
453
- invoke: &MockAuthInvoke {
454
- contract: &self.oft.address,
455
- fn_name: "set_fee_bps",
456
- args: (dst_eid, fee_bps).into_val(self.env),
457
- sub_invokes: &[],
458
- },
459
- }]);
460
- self.oft.try_set_fee_bps(&dst_eid, &fee_bps)
461
- }
462
-
463
- /// Unset fee bps for a specific destination (owner only)
464
- pub fn unset_fee_bps(&self, dst_eid: u32) {
465
- self.env.mock_auths(&[MockAuth {
466
- address: &self.owner,
467
- invoke: &MockAuthInvoke {
468
- contract: &self.oft.address,
469
- fn_name: "unset_fee_bps",
470
- args: (dst_eid,).into_val(self.env),
471
- sub_invokes: &[],
472
- },
473
- }]);
474
- self.oft.unset_fee_bps(&dst_eid);
475
- }
476
-
477
- /// Try to unset fee bps (returns Result)
478
- pub fn try_unset_fee_bps(
479
- &self,
480
- dst_eid: u32,
481
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
482
- self.env.mock_auths(&[MockAuth {
483
- address: &self.owner,
484
- invoke: &MockAuthInvoke {
485
- contract: &self.oft.address,
486
- fn_name: "unset_fee_bps",
487
- args: (dst_eid,).into_val(self.env),
488
- sub_invokes: &[],
489
- },
490
- }]);
491
- self.oft.try_unset_fee_bps(&dst_eid)
492
- }
493
-
494
- /// Set the fee deposit address (owner only)
495
- pub fn set_fee_deposit_address(&self, address: &Address) {
496
- self.env.mock_auths(&[MockAuth {
497
- address: &self.owner,
498
- invoke: &MockAuthInvoke {
499
- contract: &self.oft.address,
500
- fn_name: "set_fee_deposit_address",
501
- args: (address,).into_val(self.env),
502
- sub_invokes: &[],
503
- },
504
- }]);
505
- self.oft.set_fee_deposit_address(address);
506
- }
507
-
508
- /// Try to set fee deposit address (returns Result)
509
- pub fn try_set_fee_deposit_address(
510
- &self,
511
- address: &Address,
512
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
513
- self.env.mock_auths(&[MockAuth {
514
- address: &self.owner,
515
- invoke: &MockAuthInvoke {
516
- contract: &self.oft.address,
517
- fn_name: "set_fee_deposit_address",
518
- args: (address,).into_val(self.env),
519
- sub_invokes: &[],
520
- },
521
- }]);
522
- self.oft.try_set_fee_deposit_address(address)
523
- }
524
-
525
- /// Get the default fee bps
526
- pub fn default_fee_bps(&self) -> u64 {
527
- self.oft.default_fee_bps()
528
- }
529
-
530
- /// Get the fee bps for a specific destination
531
- pub fn fee_bps(&self, dst_eid: u32) -> u64 {
532
- self.oft.fee_bps(&dst_eid).unwrap_or(0)
533
- }
534
-
535
- /// Get the effective fee bps for a specific destination
536
- pub fn effective_fee_bps(&self, dst_eid: u32) -> u64 {
537
- self.oft.effective_fee_bps(&dst_eid)
538
- }
539
-
540
- /// Check if fee bps is set for a specific destination
541
- pub fn has_fee_bps(&self, dst_eid: u32) -> bool {
542
- self.oft.has_fee_bps(&dst_eid)
543
- }
544
-
545
- /// Get the fee deposit address
546
- pub fn fee_deposit_address(&self) -> Address {
547
- self.oft.fee_deposit_address()
548
- }
549
-
550
- // ==================== Rate Limiter Extension Helpers ====================
551
-
552
- /// Set rate limit for a direction and eid (owner only)
553
- pub fn set_rate_limit(&self, direction: &Direction, eid: u32, limit: i128, window_seconds: u64) {
554
- self.env.mock_auths(&[MockAuth {
555
- address: &self.owner,
556
- invoke: &MockAuthInvoke {
557
- contract: &self.oft.address,
558
- fn_name: "set_rate_limit",
559
- args: (direction, eid, limit, window_seconds).into_val(self.env),
560
- sub_invokes: &[],
561
- },
562
- }]);
563
- self.oft.set_rate_limit(direction, &eid, &limit, &window_seconds);
564
- }
565
-
566
- /// Try to set rate limit (returns Result)
567
- pub fn try_set_rate_limit(
568
- &self,
569
- direction: &Direction,
570
- eid: u32,
571
- limit: i128,
572
- window_seconds: u64,
573
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
574
- self.env.mock_auths(&[MockAuth {
575
- address: &self.owner,
576
- invoke: &MockAuthInvoke {
577
- contract: &self.oft.address,
578
- fn_name: "set_rate_limit",
579
- args: (direction, eid, limit, window_seconds).into_val(self.env),
580
- sub_invokes: &[],
581
- },
582
- }]);
583
- self.oft.try_set_rate_limit(direction, &eid, &limit, &window_seconds)
584
- }
585
-
586
- /// Unset rate limit for a direction and eid (owner only)
587
- pub fn unset_rate_limit(&self, direction: &Direction, eid: u32) {
588
- self.env.mock_auths(&[MockAuth {
589
- address: &self.owner,
590
- invoke: &MockAuthInvoke {
591
- contract: &self.oft.address,
592
- fn_name: "unset_rate_limit",
593
- args: (direction, eid).into_val(self.env),
594
- sub_invokes: &[],
595
- },
596
- }]);
597
- self.oft.unset_rate_limit(direction, &eid);
598
- }
599
-
600
- /// Try to unset rate limit (returns Result)
601
- pub fn try_unset_rate_limit(
602
- &self,
603
- direction: &Direction,
604
- eid: u32,
605
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
606
- self.env.mock_auths(&[MockAuth {
607
- address: &self.owner,
608
- invoke: &MockAuthInvoke {
609
- contract: &self.oft.address,
610
- fn_name: "unset_rate_limit",
611
- args: (direction, eid).into_val(self.env),
612
- sub_invokes: &[],
613
- },
614
- }]);
615
- self.oft.try_unset_rate_limit(direction, &eid)
616
- }
617
-
618
- /// Get rate limit config (limit, window_seconds)
619
- pub fn rate_limit_config(&self, direction: &Direction, eid: u32) -> (i128, u64) {
620
- self.oft.rate_limit_config(direction, &eid)
621
- }
622
-
623
- /// Get rate limit in flight
624
- pub fn rate_limit_in_flight(&self, direction: &Direction, eid: u32) -> i128 {
625
- self.oft.rate_limit_in_flight(direction, &eid)
626
- }
627
-
628
- /// Try to get rate limit in-flight (returns Result for testing error cases)
629
- pub fn try_rate_limit_in_flight(
630
- &self,
631
- direction: &Direction,
632
- eid: u32,
633
- ) -> Result<Result<i128, soroban_sdk::Error>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
634
- self.oft.try_rate_limit_in_flight(direction, &eid)
635
- }
636
-
637
- /// Get rate limit capacity
638
- pub fn rate_limit_capacity(&self, direction: &Direction, eid: u32) -> i128 {
639
- self.oft.rate_limit_capacity(direction, &eid)
640
- }
641
-
642
- // ==================== Time Helpers ====================
643
-
644
- /// Advance the ledger timestamp by the given number of seconds
645
- pub fn advance_time(&self, seconds: u64) {
646
- let current = self.env.ledger().timestamp();
647
- self.env.ledger().set_timestamp(current + seconds);
648
- }
649
-
650
- /// Set the ledger timestamp to a specific value
651
- pub fn set_timestamp(&self, timestamp: u64) {
652
- self.env.ledger().set_timestamp(timestamp);
653
- }
654
-
655
- // ==================== OFT Core Operations ====================
656
-
657
- /// Create a SendParam for testing
658
- pub fn create_send_param(&self, dst_eid: u32, amount_ld: i128, min_amount_ld: i128) -> SendParam {
659
- SendParam {
660
- dst_eid,
661
- to: BytesN::from_array(self.env, &[1u8; 32]),
662
- amount_ld,
663
- min_amount_ld,
664
- extra_options: bytes!(self.env),
665
- compose_msg: bytes!(self.env),
666
- oft_cmd: bytes!(self.env),
667
- }
668
- }
669
-
670
- /// Quote OFT to get the receipt for authorization
671
- pub fn quote_oft(&self, send_param: &SendParam) -> OFTReceipt {
672
- let (_, _, receipt) = self.oft.quote_oft(send_param);
673
- receipt
674
- }
675
-
676
- /// Try quote OFT (returns Result)
677
- pub fn try_quote_oft(
678
- &self,
679
- send_param: &SendParam,
680
- ) -> Result<
681
- Result<(crate::types::OFTLimit, soroban_sdk::Vec<crate::types::OFTFeeDetail>, OFTReceipt), soroban_sdk::Error>,
682
- Result<soroban_sdk::Error, soroban_sdk::InvokeError>,
683
- > {
684
- self.oft.try_quote_oft(send_param)
685
- }
686
-
687
- /// Quote send to get messaging fees
688
- pub fn quote_send(&self, sender: &Address, send_param: &SendParam, pay_in_zro: bool) -> MessagingFee {
689
- self.oft.quote_send(sender, send_param, &pay_in_zro)
690
- }
691
-
692
- /// Try quote send (returns Result)
693
- pub fn try_quote_send(
694
- &self,
695
- sender: &Address,
696
- send_param: &SendParam,
697
- pay_in_zro: bool,
698
- ) -> Result<Result<MessagingFee, soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>>
699
- {
700
- self.oft.try_quote_send(sender, send_param, &pay_in_zro)
701
- }
702
-
703
- /// Send tokens cross-chain with proper sender authentication and fee transfer
704
- /// Use this when OFT fee extension is configured and fee > 0
705
- pub fn send_with_fee(
706
- &self,
707
- sender: &Address,
708
- send_param: &SendParam,
709
- fee: &MessagingFee,
710
- refund_address: &Address,
711
- oft_receipt: &OFTReceipt,
712
- fee_deposit_address: &Address,
713
- ) -> (MessagingReceipt, OFTReceipt) {
714
- let fee_amount = oft_receipt.amount_sent_ld - oft_receipt.amount_received_ld;
715
-
716
- // Mock auth order must match contract execution order:
717
- // 1. Transfer fee (__charge_fee) - happens before burn
718
- // 2. Burn tokens (amount_received_ld, not amount_sent_ld)
719
- // 3. Transfer native/zro fees (__lz_send)
720
- self.env.mock_auths(&[MockAuth {
721
- address: sender,
722
- invoke: &MockAuthInvoke {
723
- contract: &self.oft.address,
724
- fn_name: "send",
725
- args: (sender, send_param, fee, refund_address).into_val(self.env),
726
- sub_invokes: &[
727
- // 1. Transfer fee to fee deposit address - happens in __charge_fee (BEFORE burn)
728
- MockAuthInvoke {
729
- contract: &self.token,
730
- fn_name: "transfer",
731
- args: (sender, fee_deposit_address, &fee_amount).into_val(self.env),
732
- sub_invokes: &[],
733
- },
734
- // 2. Burn tokens (amount_received_ld, not amount_sent_ld)
735
- MockAuthInvoke {
736
- contract: &self.token,
737
- fn_name: "burn",
738
- args: (sender, &oft_receipt.amount_received_ld).into_val(self.env),
739
- sub_invokes: &[],
740
- },
741
- // 3. Transfer native fee - happens in __lz_send
742
- MockAuthInvoke {
743
- contract: &self.native_token,
744
- fn_name: "transfer",
745
- args: (sender, &self.endpoint_client.address, &fee.native_fee).into_val(self.env),
746
- sub_invokes: &[],
747
- },
748
- // 4. Transfer zro fee - happens in __lz_send
749
- MockAuthInvoke {
750
- contract: &self.zro_token,
751
- fn_name: "transfer",
752
- args: (sender, &self.endpoint_client.address, &fee.zro_fee).into_val(self.env),
753
- sub_invokes: &[],
754
- },
755
- ],
756
- },
757
- }]);
758
- self.oft.send(sender, send_param, fee, refund_address)
759
- }
760
-
761
- /// Send tokens cross-chain without fee transfer (for cases where no fee is configured)
762
- pub fn send(
763
- &self,
764
- sender: &Address,
765
- send_param: &SendParam,
766
- fee: &MessagingFee,
767
- refund_address: &Address,
768
- oft_receipt: &OFTReceipt,
769
- ) -> (MessagingReceipt, OFTReceipt) {
770
- // When no fee is configured, amount_sent_ld == amount_received_ld
771
- // Mock auth order must match contract execution order:
772
- // 1. Burn tokens (amount_received_ld)
773
- // 2. Transfer native/zro fees (__lz_send)
774
- self.env.mock_auths(&[MockAuth {
775
- address: sender,
776
- invoke: &MockAuthInvoke {
777
- contract: &self.oft.address,
778
- fn_name: "send",
779
- args: (sender, send_param, fee, refund_address).into_val(self.env),
780
- sub_invokes: &[
781
- // 1. Burn tokens (mint-burn strategy) - amount_received_ld == amount_sent_ld when no fee
782
- MockAuthInvoke {
783
- contract: &self.token,
784
- fn_name: "burn",
785
- args: (sender, &oft_receipt.amount_received_ld).into_val(self.env),
786
- sub_invokes: &[],
787
- },
788
- // 2. Transfer native fee - happens in __lz_send
789
- MockAuthInvoke {
790
- contract: &self.native_token,
791
- fn_name: "transfer",
792
- args: (sender, &self.endpoint_client.address, &fee.native_fee).into_val(self.env),
793
- sub_invokes: &[],
794
- },
795
- // 3. Transfer zro fee - happens in __lz_send
796
- MockAuthInvoke {
797
- contract: &self.zro_token,
798
- fn_name: "transfer",
799
- args: (sender, &self.endpoint_client.address, &fee.zro_fee).into_val(self.env),
800
- sub_invokes: &[],
801
- },
802
- ],
803
- },
804
- }]);
805
- self.oft.send(sender, send_param, fee, refund_address)
806
- }
807
-
808
- /// Try send tokens cross-chain without fee (returns Result)
809
- pub fn try_send(
810
- &self,
811
- sender: &Address,
812
- send_param: &SendParam,
813
- fee: &MessagingFee,
814
- refund_address: &Address,
815
- oft_receipt: &OFTReceipt,
816
- ) -> Result<
817
- Result<(MessagingReceipt, OFTReceipt), soroban_sdk::Error>,
818
- Result<soroban_sdk::Error, soroban_sdk::InvokeError>,
819
- > {
820
- // When no fee is configured, amount_sent_ld == amount_received_ld
821
- // Mock auth order must match contract execution order:
822
- // 1. Burn tokens (amount_received_ld)
823
- // 2. Transfer native/zro fees (__lz_send)
824
- self.env.mock_auths(&[MockAuth {
825
- address: sender,
826
- invoke: &MockAuthInvoke {
827
- contract: &self.oft.address,
828
- fn_name: "send",
829
- args: (sender, send_param, fee, refund_address).into_val(self.env),
830
- sub_invokes: &[
831
- // 1. Burn tokens (mint-burn strategy) - amount_received_ld == amount_sent_ld when no fee
832
- MockAuthInvoke {
833
- contract: &self.token,
834
- fn_name: "burn",
835
- args: (sender, &oft_receipt.amount_received_ld).into_val(self.env),
836
- sub_invokes: &[],
837
- },
838
- // 2. Transfer native fee - happens in __lz_send
839
- MockAuthInvoke {
840
- contract: &self.native_token,
841
- fn_name: "transfer",
842
- args: (sender, &self.endpoint_client.address, &fee.native_fee).into_val(self.env),
843
- sub_invokes: &[],
844
- },
845
- // 3. Transfer zro fee - happens in __lz_send
846
- MockAuthInvoke {
847
- contract: &self.zro_token,
848
- fn_name: "transfer",
849
- args: (sender, &self.endpoint_client.address, &fee.zro_fee).into_val(self.env),
850
- sub_invokes: &[],
851
- },
852
- ],
853
- },
854
- }]);
855
- self.oft.try_send(sender, send_param, fee, refund_address)
856
- }
857
-
858
- /// Execute lz_receive with proper executor authentication
859
- pub fn lz_receive(
860
- &self,
861
- executor: &Address,
862
- origin: &Origin,
863
- guid: &BytesN<32>,
864
- message: &Bytes,
865
- extra_data: &Bytes,
866
- value: i128,
867
- ) {
868
- self.env.mock_auths(&[MockAuth {
869
- address: executor,
870
- invoke: &MockAuthInvoke {
871
- contract: &self.oft.address,
872
- fn_name: "lz_receive",
873
- args: (executor, origin, guid, message, extra_data, value).into_val(self.env),
874
- sub_invokes: &[],
875
- },
876
- }]);
877
- LayerZeroReceiverClient::new(self.env, &self.oft.address)
878
- .lz_receive(executor, origin, guid, message, extra_data, &value);
879
- }
880
-
881
- /// Try lz_receive (returns Result)
882
- pub fn try_lz_receive(
883
- &self,
884
- executor: &Address,
885
- origin: &Origin,
886
- guid: &BytesN<32>,
887
- message: &Bytes,
888
- extra_data: &Bytes,
889
- value: i128,
890
- ) -> Result<Result<(), soroban_sdk::ConversionError>, Result<soroban_sdk::Error, soroban_sdk::InvokeError>> {
891
- self.env.mock_auths(&[MockAuth {
892
- address: executor,
893
- invoke: &MockAuthInvoke {
894
- contract: &self.oft.address,
895
- fn_name: "lz_receive",
896
- args: (executor, origin, guid, message, extra_data, value).into_val(self.env),
897
- sub_invokes: &[],
898
- },
899
- }]);
900
- LayerZeroReceiverClient::new(self.env, &self.oft.address)
901
- .try_lz_receive(executor, origin, guid, message, extra_data, &value)
902
- }
903
- }