@layerzerolabs/protocol-stellar-v2 0.2.18 → 0.2.20

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 (213) hide show
  1. package/.turbo/turbo-build.log +303 -253
  2. package/.turbo/turbo-lint.log +66 -65
  3. package/.turbo/turbo-test.log +1312 -1282
  4. package/Cargo.lock +21 -8
  5. package/Cargo.toml +2 -0
  6. package/contracts/ERROR_SPEC.md +9 -2
  7. package/contracts/common-macros/src/contract_ttl.rs +18 -7
  8. package/contracts/common-macros/src/lib.rs +4 -4
  9. package/contracts/common-macros/src/tests/contract_ttl.rs +1 -1
  10. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap +2 -1
  11. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +7 -12
  12. package/contracts/common-macros/src/upgradeable.rs +15 -21
  13. package/contracts/message-libs/uln-302/src/events.rs +4 -0
  14. package/contracts/message-libs/uln-302/src/send_uln.rs +23 -7
  15. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +38 -64
  16. package/contracts/oapps/counter/Cargo.toml +1 -0
  17. package/contracts/oapps/counter/integration_tests/setup_uln.rs +1 -1
  18. package/contracts/oapps/oapp/src/oapp_receiver.rs +1 -1
  19. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +113 -65
  20. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +111 -82
  21. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +293 -65
  22. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +331 -56
  23. package/contracts/oapps/oft/Cargo.toml +10 -7
  24. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_oft_fee.rs +3 -4
  25. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_pausable.rs +2 -3
  26. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_rate_limiter.rs +1 -1
  27. package/contracts/oapps/oft/integration-tests/mod.rs +1 -1
  28. package/contracts/oapps/oft/integration-tests/setup.rs +28 -127
  29. package/contracts/oapps/oft/integration-tests/utils.rs +254 -21
  30. package/contracts/oapps/oft/src/extensions/oft_fee.rs +23 -8
  31. package/contracts/oapps/oft/src/extensions/pausable.rs +19 -4
  32. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +52 -28
  33. package/contracts/oapps/oft/src/lib.rs +10 -14
  34. package/contracts/oapps/oft/src/oft.rs +143 -193
  35. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +9 -11
  36. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +12 -14
  37. package/contracts/oapps/oft/src/oft_types/mod.rs +13 -0
  38. package/contracts/oapps/{oft-std → oft-core}/Cargo.toml +6 -4
  39. package/contracts/oapps/{oft-std → oft-core}/integration-tests/mod.rs +1 -1
  40. package/contracts/oapps/{oft-std → oft-core}/integration-tests/setup.rs +126 -29
  41. package/contracts/oapps/{oft → oft-core}/integration-tests/test_with_sml.rs +3 -3
  42. package/contracts/oapps/oft-core/integration-tests/utils.rs +201 -0
  43. package/contracts/oapps/oft-core/src/lib.rs +18 -0
  44. package/contracts/oapps/oft-core/src/oft_core.rs +479 -0
  45. package/contracts/oapps/{oft → oft-core}/src/tests/mod.rs +0 -2
  46. package/contracts/oapps/{oft → oft-core}/src/tests/test_lz_receive.rs +7 -7
  47. package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_msg_codec.rs +4 -4
  48. package/contracts/oapps/{oft → oft-core}/src/tests/test_resolve_address.rs +3 -3
  49. package/contracts/oapps/{oft → oft-core}/src/tests/test_utils.rs +46 -27
  50. package/contracts/oapps/{oft → oft-core}/src/utils.rs +1 -1
  51. package/contracts/upgrader/src/lib.rs +30 -57
  52. package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract1.wasm +0 -0
  53. package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract2.wasm +0 -0
  54. package/contracts/upgrader/src/tests/test_upgrader.rs +44 -35
  55. package/contracts/utils/src/buffer_reader.rs +1 -0
  56. package/contracts/utils/src/errors.rs +8 -2
  57. package/contracts/utils/src/ownable.rs +125 -3
  58. package/contracts/utils/src/tests/option_ext.rs +1 -1
  59. package/contracts/utils/src/tests/ownable.rs +445 -7
  60. package/contracts/utils/src/tests/ttl_configurable.rs +2 -2
  61. package/contracts/utils/src/tests/upgradeable.rs +372 -175
  62. package/contracts/utils/src/ttl_configurable.rs +3 -3
  63. package/contracts/utils/src/upgradeable.rs +48 -23
  64. package/contracts/workers/dvn/Cargo.toml +1 -0
  65. package/contracts/workers/dvn/src/auth.rs +12 -42
  66. package/contracts/workers/dvn/src/dvn.rs +16 -31
  67. package/contracts/workers/dvn/src/errors.rs +0 -1
  68. package/contracts/workers/dvn/src/interfaces/dvn.rs +35 -0
  69. package/contracts/workers/dvn/src/lib.rs +4 -3
  70. package/contracts/workers/dvn/src/tests/auth.rs +1 -1
  71. package/contracts/workers/dvn/src/tests/dvn.rs +19 -15
  72. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +2 -4
  73. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +1 -3
  74. package/contracts/workers/dvn/src/tests/setup.rs +5 -9
  75. package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
  76. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +3 -5
  77. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +2 -3
  78. package/contracts/workers/executor/Cargo.toml +1 -0
  79. package/contracts/workers/executor/src/executor.rs +15 -26
  80. package/contracts/workers/executor-fee-lib/Cargo.toml +2 -1
  81. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +63 -5
  82. package/contracts/workers/executor-fee-lib/src/executor_option.rs +28 -1
  83. package/contracts/workers/executor-fee-lib/src/lib.rs +3 -0
  84. package/contracts/workers/executor-fee-lib/src/tests/executor_fee_lib.rs +701 -0
  85. package/contracts/workers/executor-fee-lib/src/tests/executor_option.rs +370 -0
  86. package/contracts/workers/executor-fee-lib/src/tests/mod.rs +4 -0
  87. package/contracts/workers/executor-fee-lib/src/tests/setup.rs +60 -0
  88. package/contracts/workers/executor-helper/src/lib.rs +3 -0
  89. package/contracts/workers/executor-helper/src/tests/executor_helper.rs +184 -0
  90. package/contracts/workers/executor-helper/src/tests/mod.rs +2 -0
  91. package/contracts/workers/executor-helper/src/tests/setup.rs +366 -0
  92. package/contracts/workers/fee-lib-interfaces/Cargo.toml +14 -0
  93. package/contracts/workers/{worker/src/interfaces/mod.rs → fee-lib-interfaces/src/lib.rs} +4 -3
  94. package/contracts/workers/price-feed/Cargo.toml +2 -1
  95. package/contracts/workers/price-feed/src/events.rs +1 -1
  96. package/contracts/workers/price-feed/src/lib.rs +3 -0
  97. package/contracts/workers/price-feed/src/price_feed.rs +6 -12
  98. package/contracts/workers/price-feed/src/storage.rs +1 -1
  99. package/contracts/workers/price-feed/src/tests/mod.rs +2 -0
  100. package/contracts/workers/price-feed/src/tests/price_feed.rs +869 -0
  101. package/contracts/workers/price-feed/src/tests/setup.rs +70 -0
  102. package/contracts/workers/price-feed/src/types.rs +1 -1
  103. package/contracts/workers/worker/src/errors.rs +0 -3
  104. package/contracts/workers/worker/src/lib.rs +0 -2
  105. package/contracts/workers/worker/src/storage.rs +32 -29
  106. package/contracts/workers/worker/src/tests/setup.rs +1 -7
  107. package/contracts/workers/worker/src/tests/worker.rs +50 -42
  108. package/contracts/workers/worker/src/worker.rs +49 -58
  109. package/package.json +4 -5
  110. package/sdk/.turbo/turbo-test.log +229 -217
  111. package/sdk/dist/generated/bml.d.ts +39 -1
  112. package/sdk/dist/generated/bml.js +33 -8
  113. package/sdk/dist/generated/counter.d.ts +131 -3
  114. package/sdk/dist/generated/counter.js +41 -10
  115. package/sdk/dist/generated/dvn.d.ts +431 -362
  116. package/sdk/dist/generated/dvn.js +80 -55
  117. package/sdk/dist/generated/dvn_fee_lib.d.ts +327 -251
  118. package/sdk/dist/generated/dvn_fee_lib.js +55 -57
  119. package/sdk/dist/generated/endpoint.d.ts +131 -3
  120. package/sdk/dist/generated/endpoint.js +41 -10
  121. package/sdk/dist/generated/executor.d.ts +503 -339
  122. package/sdk/dist/generated/executor.js +80 -48
  123. package/sdk/dist/generated/executor_fee_lib.d.ts +395 -319
  124. package/sdk/dist/generated/executor_fee_lib.js +54 -56
  125. package/sdk/dist/generated/executor_helper.d.ts +53 -187
  126. package/sdk/dist/generated/executor_helper.js +47 -29
  127. package/sdk/dist/generated/layerzero_view.d.ts +1271 -0
  128. package/sdk/dist/generated/layerzero_view.js +294 -0
  129. package/sdk/dist/generated/oft.d.ts +1851 -0
  130. package/sdk/dist/generated/oft.js +347 -0
  131. package/sdk/dist/generated/price_feed.d.ts +329 -253
  132. package/sdk/dist/generated/price_feed.js +55 -57
  133. package/sdk/dist/generated/sml.d.ts +131 -3
  134. package/sdk/dist/generated/sml.js +41 -10
  135. package/sdk/dist/generated/treasury.d.ts +131 -3
  136. package/sdk/dist/generated/treasury.js +41 -10
  137. package/sdk/dist/generated/uln302.d.ts +131 -3
  138. package/sdk/dist/generated/uln302.js +43 -12
  139. package/sdk/dist/generated/upgrader.d.ts +201 -15
  140. package/sdk/dist/generated/upgrader.js +99 -1
  141. package/sdk/dist/index.d.ts +2 -2
  142. package/sdk/dist/index.js +3 -3
  143. package/sdk/package.json +3 -2
  144. package/sdk/src/index.ts +3 -3
  145. package/sdk/test/oft-sml.test.ts +20 -20
  146. package/sdk/test/upgrader.test.ts +2 -3
  147. package/sdk/turbo.json +8 -0
  148. package/tools/ts-bindings-gen/Cargo.toml +2 -0
  149. package/tools/ts-bindings-gen/src/main.rs +53 -5
  150. package/turbo.json +0 -2
  151. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +0 -23
  152. package/contracts/oapps/oft/src/interfaces/mod.rs +0 -3
  153. package/contracts/oapps/oft/src/oft_impl.rs +0 -201
  154. package/contracts/oapps/oft/src/tests/extensions/mod.rs +0 -11
  155. package/contracts/oapps/oft/src/tests/extensions/setup.rs +0 -917
  156. package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +0 -751
  157. package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +0 -434
  158. package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +0 -1080
  159. package/contracts/oapps/oft-std/integration-tests/utils.rs +0 -427
  160. package/contracts/oapps/oft-std/src/lib.rs +0 -16
  161. package/contracts/oapps/oft-std/src/oft.rs +0 -174
  162. package/sdk/dist/generated/oft_std.d.ts +0 -1722
  163. package/sdk/dist/generated/oft_std.js +0 -316
  164. package/sdk/dist/wasm/blocked-message-lib.d.ts +0 -1
  165. package/sdk/dist/wasm/blocked-message-lib.js +0 -2
  166. package/sdk/dist/wasm/counter.d.ts +0 -1
  167. package/sdk/dist/wasm/counter.js +0 -2
  168. package/sdk/dist/wasm/dvn-fee-lib.d.ts +0 -1
  169. package/sdk/dist/wasm/dvn-fee-lib.js +0 -2
  170. package/sdk/dist/wasm/dvn.d.ts +0 -1
  171. package/sdk/dist/wasm/dvn.js +0 -2
  172. package/sdk/dist/wasm/endpoint-v2.d.ts +0 -1
  173. package/sdk/dist/wasm/endpoint-v2.js +0 -2
  174. package/sdk/dist/wasm/executor-fee-lib.d.ts +0 -1
  175. package/sdk/dist/wasm/executor-fee-lib.js +0 -2
  176. package/sdk/dist/wasm/executor-helper.d.ts +0 -1
  177. package/sdk/dist/wasm/executor-helper.js +0 -2
  178. package/sdk/dist/wasm/executor.d.ts +0 -1
  179. package/sdk/dist/wasm/executor.js +0 -2
  180. package/sdk/dist/wasm/layerzero-views.d.ts +0 -1
  181. package/sdk/dist/wasm/layerzero-views.js +0 -2
  182. package/sdk/dist/wasm/oft-std.d.ts +0 -1
  183. package/sdk/dist/wasm/oft-std.js +0 -2
  184. package/sdk/dist/wasm/price-feed.d.ts +0 -1
  185. package/sdk/dist/wasm/price-feed.js +0 -2
  186. package/sdk/dist/wasm/simple-message-lib.d.ts +0 -1
  187. package/sdk/dist/wasm/simple-message-lib.js +0 -2
  188. package/sdk/dist/wasm/treasury.d.ts +0 -1
  189. package/sdk/dist/wasm/treasury.js +0 -2
  190. package/sdk/dist/wasm/uln302.d.ts +0 -1
  191. package/sdk/dist/wasm/uln302.js +0 -2
  192. package/sdk/dist/wasm/upgrader.d.ts +0 -1
  193. package/sdk/dist/wasm/upgrader.js +0 -2
  194. package/sdk/dist/wasm.d.ts +0 -15
  195. package/sdk/dist/wasm.js +0 -15
  196. /package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/mod.rs +0 -0
  197. /package/contracts/oapps/{oft → oft-core}/src/codec/mod.rs +0 -0
  198. /package/contracts/oapps/{oft → oft-core}/src/codec/oft_compose_msg_codec.rs +0 -0
  199. /package/contracts/oapps/{oft → oft-core}/src/codec/oft_msg_codec.rs +0 -0
  200. /package/contracts/oapps/{oft → oft-core}/src/errors.rs +0 -0
  201. /package/contracts/oapps/{oft → oft-core}/src/events.rs +0 -0
  202. /package/contracts/oapps/{oft → oft-core}/src/storage.rs +0 -0
  203. /package/contracts/oapps/{oft → oft-core}/src/tests/test_decimals.rs +0 -0
  204. /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_compose_msg_codec.rs +0 -0
  205. /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_version.rs +0 -0
  206. /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_oft.rs +0 -0
  207. /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_send.rs +0 -0
  208. /package/contracts/oapps/{oft → oft-core}/src/tests/test_send.rs +0 -0
  209. /package/contracts/oapps/{oft → oft-core}/src/tests/test_token.rs +0 -0
  210. /package/contracts/oapps/{oft → oft-core}/src/types.rs +0 -0
  211. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/dvn_fee_lib.rs +0 -0
  212. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/executor_fee_lib.rs +0 -0
  213. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/price_feed.rs +0 -0
@@ -1,141 +1,39 @@
1
- //! Integration test setup for OFT.
1
+ //! Integration test setup for OFT-STD with real EndpointV2 and SimpleMessageLib.
2
2
  //!
3
- //! This file contains TestOFT contract and test setup utilities.
3
+ //! This file contains test setup utilities for OFT-STD with all extensions enabled.
4
4
 
5
- extern crate self as oft;
6
5
  extern crate std;
7
6
 
8
- use crate::integration_tests::utils::{address_to_peer_bytes32, peer_bytes32_to_address};
9
- use common_macros::contract_impl;
10
- use endpoint_v2::{EndpointV2, EndpointV2Client, ILayerZeroComposer, Origin};
11
- use oapp::oapp_receiver::LzReceiveInternal;
12
- use oft::{
13
- initialize_oft,
14
- oft::{OFTClient, OFTInternal, OFT},
15
- oft_impl,
16
- storage::OFTStorage,
17
- types::OFTReceipt,
7
+ use crate::{
8
+ integration_tests::utils::{address_to_peer_bytes32, peer_bytes32_to_address},
9
+ oft::{OFTClient, OFT},
10
+ oft_types::OftType,
18
11
  };
12
+ use endpoint_v2::{EndpointV2, EndpointV2Client};
19
13
  use simple_message_lib::{SimpleMessageLib, SimpleMessageLibClient};
20
14
  use soroban_sdk::{
21
- contract, contractimpl, contracttype, log, symbol_short,
15
+ contract, contractimpl, log,
22
16
  testutils::{Address as _, MockAuth, MockAuthInvoke},
23
- token::{StellarAssetClient, TokenClient},
24
- Address, Bytes, BytesN, Env, IntoVal,
17
+ token::TokenClient,
18
+ Address, BytesN, Env, IntoVal,
25
19
  };
26
20
 
27
21
  // ============================================================================
28
- // Test OFT Contract
22
+ // Dummy Recipient - used to create valid contract addresses for recipients
29
23
  // ============================================================================
30
24
 
31
- #[oapp_macros::oapp]
32
- pub struct TestOFT;
33
-
34
- impl LzReceiveInternal for TestOFT {
35
- fn __lz_receive(
36
- env: &Env,
37
- origin: &Origin,
38
- guid: &BytesN<32>,
39
- message: &Bytes,
40
- extra_data: &Bytes,
41
- executor: &Address,
42
- value: i128,
43
- ) {
44
- oft_impl::lz_receive::<Self>(env, executor, origin, guid, message, extra_data, value)
45
- }
46
- }
47
-
48
- #[contract_impl]
49
- impl TestOFT {
50
- pub fn __constructor(
51
- env: &Env,
52
- token: &Address,
53
- owner: &Address,
54
- endpoint: &Address,
55
- delegate: &Option<Address>,
56
- shared_decimals: u32,
57
- ) {
58
- initialize_oft::<Self>(env, owner, token, endpoint, delegate, shared_decimals)
59
- }
60
- }
61
-
62
- #[contractimpl(contracttrait)]
63
- impl OFT for TestOFT {}
64
-
65
- impl OFTInternal for TestOFT {
66
- fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
67
- // Get the receipt (handles decimal conversion, fees, etc.)
68
- let receipt = Self::__debit_view(env, amount_ld, min_amount_ld, dst_eid);
69
- // Actually burn tokens from sender
70
- StellarAssetClient::new(env, &OFTStorage::token(env).unwrap()).burn(sender, &receipt.amount_sent_ld);
71
- receipt
72
- }
73
-
74
- fn __credit(env: &Env, to: &Address, amount_ld: i128, _src_eid: u32) -> i128 {
75
- // Actually mint tokens to recipient
76
- StellarAssetClient::new(env, &OFTStorage::token(env).unwrap()).mint(to, &amount_ld);
77
- amount_ld
78
- }
79
- }
80
-
81
- // ============================================================================
82
- // Dummy Composer for testing compose messages
83
- // ============================================================================
84
-
85
- #[contracttype]
86
- pub struct ComposeMessage {
87
- pub executor: Address,
88
- pub from: Address,
89
- pub guid: BytesN<32>,
90
- pub index: u32,
91
- pub message: Bytes,
92
- pub extra_data: Bytes,
93
- pub value: i128,
94
- }
95
-
96
25
  #[contract]
97
- pub struct DummyComposer;
26
+ pub struct DummyRecipient;
98
27
 
99
- #[contract_impl]
100
- impl DummyComposer {
101
- pub fn __constructor(env: &Env, endpoint: &Address) {
102
- env.storage().instance().set(&symbol_short!("endpoint"), endpoint);
103
- }
104
-
105
- pub fn compose_message(env: &Env) -> Option<ComposeMessage> {
106
- env.storage().instance().get(&symbol_short!("msg"))
107
- }
28
+ #[contractimpl]
29
+ impl DummyRecipient {
30
+ pub fn __constructor(_env: &Env) {}
108
31
  }
109
32
 
110
- #[contract_impl]
111
- impl ILayerZeroComposer for DummyComposer {
112
- fn lz_compose(
113
- env: &Env,
114
- executor: &Address,
115
- from: &Address,
116
- guid: &BytesN<32>,
117
- index: u32,
118
- message: &Bytes,
119
- extra_data: &Bytes,
120
- value: i128,
121
- ) {
122
- let endpoint_address: Address = env.storage().instance().get(&symbol_short!("endpoint")).unwrap();
123
- let endpoint = endpoint_v2::MessagingComposerClient::new(env, &endpoint_address);
124
- endpoint.clear_compose(&env.current_contract_address(), from, guid, &index, message);
125
-
126
- env.storage().instance().set(
127
- &symbol_short!("msg"),
128
- &ComposeMessage {
129
- executor: executor.clone(),
130
- from: from.clone(),
131
- guid: guid.clone(),
132
- index,
133
- message: message.clone(),
134
- extra_data: extra_data.clone(),
135
- value,
136
- },
137
- );
138
- }
33
+ /// Creates a valid recipient address by deploying a dummy contract.
34
+ /// Use this in tests when the address needs to pass the `.exists()` check.
35
+ pub fn create_recipient_address(env: &Env) -> Address {
36
+ env.register(DummyRecipient, ())
139
37
  }
140
38
 
141
39
  // ============================================================================
@@ -146,16 +44,16 @@ pub struct ChainSetup<'a> {
146
44
  pub eid: u32,
147
45
  pub owner: Address,
148
46
  pub native_token: Address,
47
+ pub zro_token: Address,
149
48
  pub oft_token: Address,
150
49
  pub endpoint: EndpointV2Client<'a>,
151
50
  pub sml: SimpleMessageLibClient<'a>,
152
51
  pub oft: OFTClient<'a>,
153
- pub composer: DummyComposerClient<'a>,
52
+ pub fee_collector: Address,
154
53
  }
155
54
 
156
55
  pub struct TestSetup<'a> {
157
56
  pub env: Env,
158
-
159
57
  pub chain_a: ChainSetup<'a>,
160
58
  pub chain_b: ChainSetup<'a>,
161
59
  }
@@ -163,9 +61,13 @@ pub struct TestSetup<'a> {
163
61
  fn setup_chain<'a>(env: &Env) -> ChainSetup<'a> {
164
62
  let owner = Address::generate(env);
165
63
 
64
+ // Create native token FIRST - this must match the endpoint's NATIVE_TOKEN constant
166
65
  let sac = env.register_stellar_asset_contract_v2(owner.clone());
167
66
  let native_token = sac.address();
168
67
 
68
+ // Generate fee_collector AFTER native_token to not affect the address derivation
69
+ let fee_collector = Address::generate(env);
70
+
169
71
  // Create ZRO token
170
72
  let zro_sac = env.register_stellar_asset_contract_v2(owner.clone());
171
73
  let zro_token = zro_sac.address();
@@ -179,13 +81,12 @@ fn setup_chain<'a>(env: &Env) -> ChainSetup<'a> {
179
81
  let sml_address = env.register(SimpleMessageLib, (&owner, &endpoint_address, &fee_recipient));
180
82
  let delegate: Option<Address> = Some(owner.clone());
181
83
  let shared_decimals: u32 = 6; // Default shared decimals
182
- let oft_address = env.register(TestOFT, (&oft_token, &owner, &endpoint_address, &delegate, &shared_decimals));
183
- let composer_address = env.register(DummyComposer, (&endpoint_address,));
84
+ let mode = OftType::MintBurn;
85
+ let oft_address = env.register(OFT, (&oft_token, &owner, &endpoint_address, &delegate, &shared_decimals, &mode));
184
86
 
185
87
  let endpoint = EndpointV2Client::new(env, &endpoint_address);
186
88
  let sml = SimpleMessageLibClient::new(env, &sml_address);
187
89
  let oft = OFTClient::new(env, &oft_address);
188
- let composer = DummyComposerClient::new(env, &composer_address);
189
90
 
190
91
  // Set ZRO token in endpoint
191
92
  env.mock_auths(&[MockAuth {
@@ -202,7 +103,7 @@ fn setup_chain<'a>(env: &Env) -> ChainSetup<'a> {
202
103
  register_library(env, &owner, &endpoint, &sml.address);
203
104
 
204
105
  let eid = endpoint.eid();
205
- ChainSetup { eid, owner, native_token, oft_token, endpoint, sml, oft, composer }
106
+ ChainSetup { eid, owner, native_token, zro_token, oft_token, endpoint, sml, oft, fee_collector }
206
107
  }
207
108
 
208
109
  pub fn setup<'a>() -> TestSetup<'a> {
@@ -1,20 +1,22 @@
1
- use core::ops::Mul;
1
+ //! Utility functions for OFT-STD integration tests.
2
2
 
3
- use crate::{
4
- codec::{oft_compose_msg_codec::OFTComposeMsg, oft_msg_codec},
5
- integration_tests::setup::{decode_packet, ChainSetup},
6
- types::{OFTFeeDetail, OFTLimit, OFTReceipt, SendParam},
7
- };
3
+ use crate::extensions::rate_limiter::Direction;
4
+ use crate::integration_tests::setup::{decode_packet, ChainSetup};
8
5
  use endpoint_v2::{MessagingFee, Origin, OutboundPacket};
9
6
  use message_lib_common::packet_codec_v1;
7
+ use oft_core::types::{OFTFeeDetail, OFTLimit, OFTReceipt, SendParam};
10
8
  use soroban_sdk::{
11
9
  address_payload::AddressPayload,
12
- testutils::{Events, MockAuth, MockAuthInvoke},
10
+ testutils::{Events, Ledger, MockAuth, MockAuthInvoke},
13
11
  token::StellarAssetClient,
14
12
  xdr::ToXdr,
15
13
  Address, Bytes, BytesN, Env, IntoVal, Map, Symbol, Val, Vec,
16
14
  };
17
15
 
16
+ // ============================================================================
17
+ // Address Conversion Utilities
18
+ // ============================================================================
19
+
18
20
  pub fn address_to_peer_bytes32(address: &Address) -> BytesN<32> {
19
21
  match address.to_payload().unwrap() {
20
22
  AddressPayload::ContractIdHash(payload) => payload,
@@ -26,6 +28,16 @@ pub fn peer_bytes32_to_address(env: &Env, bytes32: &BytesN<32>) -> Address {
26
28
  AddressPayload::ContractIdHash(bytes32.clone()).to_address(env)
27
29
  }
28
30
 
31
+ #[allow(dead_code)]
32
+ pub fn create_recipient_address(env: &Env) -> Address {
33
+ let bytes = BytesN::from_array(env, &[0u8; 32]);
34
+ peer_bytes32_to_address(env, &bytes)
35
+ }
36
+
37
+ // ============================================================================
38
+ // OFT Core Operations
39
+ // ============================================================================
40
+
29
41
  pub fn quote_oft(chain: &ChainSetup<'_>, send_param: &SendParam) -> (OFTLimit, Vec<OFTFeeDetail>, OFTReceipt) {
30
42
  chain.oft.quote_oft(send_param)
31
43
  }
@@ -49,6 +61,7 @@ pub fn quote_send(
49
61
  chain.oft.quote_send(sender, send_param, &pay_in_zro)
50
62
  }
51
63
 
64
+ /// Send without fee (standard OFT send)
52
65
  pub fn send(
53
66
  env: &Env,
54
67
  chain: &ChainSetup<'_>,
@@ -83,6 +96,88 @@ pub fn send(
83
96
  chain.oft.send(sender, send_param, fee, refund_address);
84
97
  }
85
98
 
99
+ /// Send with fee (OFT fee extension enabled)
100
+ /// Order: transfer fee to deposit -> burn tokens -> transfer native fee
101
+ pub fn send_with_fee(
102
+ env: &Env,
103
+ chain: &ChainSetup<'_>,
104
+ sender: &Address,
105
+ send_param: &SendParam,
106
+ fee: &MessagingFee,
107
+ refund_address: &Address,
108
+ oft_receipt: &OFTReceipt,
109
+ fee_deposit_address: &Address,
110
+ ) {
111
+ let fee_amount = oft_receipt.amount_sent_ld - oft_receipt.amount_received_ld;
112
+ env.mock_auths(&[MockAuth {
113
+ address: sender,
114
+ invoke: &MockAuthInvoke {
115
+ contract: &chain.oft.address,
116
+ fn_name: "send",
117
+ args: (sender, send_param, fee, refund_address).into_val(env),
118
+ sub_invokes: &[
119
+ MockAuthInvoke {
120
+ contract: &chain.oft_token,
121
+ fn_name: "transfer",
122
+ args: (sender, fee_deposit_address, &fee_amount).into_val(env),
123
+ sub_invokes: &[],
124
+ },
125
+ MockAuthInvoke {
126
+ contract: &chain.oft_token,
127
+ fn_name: "burn",
128
+ args: (sender, &oft_receipt.amount_received_ld).into_val(env),
129
+ sub_invokes: &[],
130
+ },
131
+ MockAuthInvoke {
132
+ contract: &chain.native_token,
133
+ fn_name: "transfer",
134
+ args: (sender, &chain.endpoint.address, &fee.native_fee).into_val(env),
135
+ sub_invokes: &[],
136
+ },
137
+ ],
138
+ },
139
+ }]);
140
+ chain.oft.send(sender, send_param, fee, refund_address);
141
+ }
142
+
143
+ pub fn try_send(
144
+ env: &Env,
145
+ chain: &ChainSetup<'_>,
146
+ sender: &Address,
147
+ send_param: &SendParam,
148
+ fee: &MessagingFee,
149
+ refund_address: &Address,
150
+ oft_receipt: &OFTReceipt,
151
+ ) -> bool {
152
+ env.mock_auths(&[MockAuth {
153
+ address: sender,
154
+ invoke: &MockAuthInvoke {
155
+ contract: &chain.oft.address,
156
+ fn_name: "send",
157
+ args: (sender, send_param, fee, refund_address).into_val(env),
158
+ sub_invokes: &[
159
+ MockAuthInvoke {
160
+ contract: &chain.native_token,
161
+ fn_name: "transfer",
162
+ args: (sender, &chain.endpoint.address, &fee.native_fee).into_val(env),
163
+ sub_invokes: &[],
164
+ },
165
+ MockAuthInvoke {
166
+ contract: &chain.oft_token,
167
+ fn_name: "burn",
168
+ args: (sender, &oft_receipt.amount_received_ld).into_val(env),
169
+ sub_invokes: &[],
170
+ },
171
+ ],
172
+ },
173
+ }]);
174
+ chain.oft.try_send(sender, send_param, fee, refund_address).is_ok()
175
+ }
176
+
177
+ // ============================================================================
178
+ // Packet Handling
179
+ // ============================================================================
180
+
86
181
  pub fn validate_packet(env: &Env, chain: &ChainSetup<'_>, packet_event: &(Bytes, Bytes, Address)) {
87
182
  let packet = decode_packet(env, &packet_event.0);
88
183
  let encoded_header = packet_codec_v1::encode_packet_header(env, &packet);
@@ -131,26 +226,30 @@ pub fn lz_receive(
131
226
  );
132
227
  }
133
228
 
134
- pub fn lz_compose(
229
+ pub fn try_lz_receive(
135
230
  env: &Env,
136
231
  chain: &ChainSetup<'_>,
137
232
  executor: &Address,
138
233
  packet: &OutboundPacket,
139
- index: u32,
140
- extra_data: &Bytes,
234
+ recipient: &Address,
141
235
  value: i128,
142
- ) {
143
- let oft_msg = oft_msg_codec::OFTMessage::decode(&packet.message);
144
- let oft_compose_msg = OFTComposeMsg {
145
- nonce: packet.nonce,
146
- src_eid: packet.src_eid,
147
- amount_ld: (oft_msg.amount_sd as i128).mul(chain.oft.decimal_conversion_rate()),
148
- compose_from: oft_msg.compose_from.unwrap(),
149
- compose_msg: oft_msg.compose_msg.unwrap(),
150
- }
151
- .encode(&env);
236
+ ) -> bool {
237
+ let origin =
238
+ Origin { src_eid: packet.src_eid, sender: address_to_peer_bytes32(&packet.sender), nonce: packet.nonce };
239
+ let extra_options = recipient.to_xdr(env);
152
240
 
153
- chain.composer.lz_compose(executor, &chain.oft.address, &packet.guid, &index, &oft_compose_msg, extra_data, &value);
241
+ env.mock_auths(&[MockAuth {
242
+ address: executor,
243
+ invoke: &MockAuthInvoke {
244
+ contract: &chain.oft.address,
245
+ fn_name: "lz_receive",
246
+ args: (executor, &origin, &packet.guid, &packet.message, &extra_options, &value).into_val(env),
247
+ sub_invokes: &[],
248
+ },
249
+ }]);
250
+ endpoint_v2::LayerZeroReceiverClient::new(env, &chain.oft.address)
251
+ .try_lz_receive(executor, &origin, &packet.guid, &packet.message, &extra_options, &value)
252
+ .is_ok()
154
253
  }
155
254
 
156
255
  // returns (encoded_payload, options, send_library)
@@ -172,6 +271,10 @@ pub fn scan_packet_sent_event(env: &Env, endpoint: &Address) -> Option<(Bytes, B
172
271
  packet
173
272
  }
174
273
 
274
+ // ============================================================================
275
+ // Token Operations
276
+ // ============================================================================
277
+
175
278
  pub fn mint_to(env: &Env, owner: &Address, token: &Address, to: &Address, amount: i128) {
176
279
  env.mock_auths(&[MockAuth {
177
280
  address: owner,
@@ -199,3 +302,133 @@ pub fn transfer_sac_admin(env: &Env, owner: &Address, token: &Address, new_admin
199
302
  }]);
200
303
  StellarAssetClient::new(env, token).set_admin(new_admin);
201
304
  }
305
+
306
+ pub fn token_balance(env: &Env, token: &Address, account: &Address) -> i128 {
307
+ soroban_sdk::token::TokenClient::new(env, token).balance(account)
308
+ }
309
+
310
+ // ============================================================================
311
+ // Pausable Extension Operations
312
+ // ============================================================================
313
+
314
+ pub fn set_paused(env: &Env, chain: &ChainSetup<'_>, paused: bool) {
315
+ env.mock_auths(&[MockAuth {
316
+ address: &chain.owner,
317
+ invoke: &MockAuthInvoke {
318
+ contract: &chain.oft.address,
319
+ fn_name: "set_paused",
320
+ args: (&paused,).into_val(env),
321
+ sub_invokes: &[],
322
+ },
323
+ }]);
324
+ chain.oft.set_paused(&paused);
325
+ }
326
+
327
+ pub fn is_paused(chain: &ChainSetup<'_>) -> bool {
328
+ chain.oft.is_paused()
329
+ }
330
+
331
+ // ============================================================================
332
+ // OFT Fee Extension Operations
333
+ // ============================================================================
334
+
335
+ pub fn set_fee_deposit_address(env: &Env, chain: &ChainSetup<'_>, deposit_address: &Address) {
336
+ env.mock_auths(&[MockAuth {
337
+ address: &chain.owner,
338
+ invoke: &MockAuthInvoke {
339
+ contract: &chain.oft.address,
340
+ fn_name: "set_fee_deposit_address",
341
+ args: (deposit_address,).into_val(env),
342
+ sub_invokes: &[],
343
+ },
344
+ }]);
345
+ chain.oft.set_fee_deposit_address(deposit_address);
346
+ }
347
+
348
+ pub fn set_default_fee_bps(env: &Env, chain: &ChainSetup<'_>, fee_bps: u64) {
349
+ env.mock_auths(&[MockAuth {
350
+ address: &chain.owner,
351
+ invoke: &MockAuthInvoke {
352
+ contract: &chain.oft.address,
353
+ fn_name: "set_default_fee_bps",
354
+ args: (&fee_bps,).into_val(env),
355
+ sub_invokes: &[],
356
+ },
357
+ }]);
358
+ chain.oft.set_default_fee_bps(&fee_bps);
359
+ }
360
+
361
+ pub fn set_fee_bps(env: &Env, chain: &ChainSetup<'_>, dst_eid: u32, fee_bps: u64) {
362
+ env.mock_auths(&[MockAuth {
363
+ address: &chain.owner,
364
+ invoke: &MockAuthInvoke {
365
+ contract: &chain.oft.address,
366
+ fn_name: "set_fee_bps",
367
+ args: (&dst_eid, &fee_bps).into_val(env),
368
+ sub_invokes: &[],
369
+ },
370
+ }]);
371
+ chain.oft.set_fee_bps(&dst_eid, &fee_bps);
372
+ }
373
+
374
+ // ============================================================================
375
+ // Rate Limiter Extension Operations
376
+ // ============================================================================
377
+
378
+ pub fn set_rate_limit(
379
+ env: &Env,
380
+ chain: &ChainSetup<'_>,
381
+ direction: &Direction,
382
+ dst_eid: u32,
383
+ limit: i128,
384
+ window_seconds: u64,
385
+ ) {
386
+ env.mock_auths(&[MockAuth {
387
+ address: &chain.owner,
388
+ invoke: &MockAuthInvoke {
389
+ contract: &chain.oft.address,
390
+ fn_name: "set_rate_limit",
391
+ args: (direction, &dst_eid, &limit, &window_seconds).into_val(env),
392
+ sub_invokes: &[],
393
+ },
394
+ }]);
395
+ chain.oft.set_rate_limit(direction, &dst_eid, &limit, &window_seconds);
396
+ }
397
+
398
+ pub fn rate_limit_capacity(chain: &ChainSetup<'_>, direction: &Direction, eid: u32) -> i128 {
399
+ chain.oft.rate_limit_capacity(direction, &eid)
400
+ }
401
+
402
+ pub fn rate_limit_in_flight(chain: &ChainSetup<'_>, direction: &Direction, eid: u32) -> i128 {
403
+ chain.oft.rate_limit_in_flight(direction, &eid)
404
+ }
405
+
406
+ // ============================================================================
407
+ // Time Utilities
408
+ // ============================================================================
409
+
410
+ pub fn advance_time(env: &Env, seconds: u64) {
411
+ let current = env.ledger().timestamp();
412
+ env.ledger().set_timestamp(current + seconds);
413
+ }
414
+
415
+ #[allow(dead_code)]
416
+ pub fn set_timestamp(env: &Env, timestamp: u64) {
417
+ env.ledger().set_timestamp(timestamp);
418
+ }
419
+
420
+ // ============================================================================
421
+ // SendParam Builder
422
+ // ============================================================================
423
+
424
+ pub fn create_send_param(env: &Env, dst_eid: u32, amount_ld: i128, min_amount_ld: i128, to: &BytesN<32>) -> SendParam {
425
+ SendParam {
426
+ dst_eid,
427
+ to: to.clone(),
428
+ amount_ld,
429
+ min_amount_ld,
430
+ extra_options: Bytes::new(env),
431
+ compose_msg: Bytes::new(env),
432
+ oft_cmd: Bytes::new(env),
433
+ }
434
+ }
@@ -6,6 +6,10 @@ use utils::{option_ext::OptionExt, ownable::Ownable};
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 {
11
15
  #[instance(u64)]
@@ -19,14 +23,22 @@ pub enum OFTFeeStorage {
19
23
  FeeDepositAddress,
20
24
  }
21
25
 
26
+ // =========================================================================
27
+ // Errors
28
+ // =========================================================================
29
+
22
30
  #[contract_error]
23
31
  pub enum OFTFeeError {
24
- InvalidFeeBps = 2200,
32
+ InvalidFeeBps = 3100,
25
33
  InvalidFeeDepositAddress,
26
34
  NotFound,
27
35
  SameValue,
28
36
  }
29
37
 
38
+ // =========================================================================
39
+ // Events
40
+ // =========================================================================
41
+
30
42
  #[contractevent]
31
43
  #[derive(Clone, Debug, Eq, PartialEq)]
32
44
  pub struct DefaultFeeBpsSet {
@@ -52,8 +64,12 @@ pub struct FeeDepositAddressSet {
52
64
  pub fee_deposit_address: Address,
53
65
  }
54
66
 
67
+ // =========================================================================
68
+ // Trait With Default Implementations
69
+ // =========================================================================
70
+
55
71
  #[contract_trait]
56
- pub trait OFTFee: OFTFeeInternal + Ownable + Sized {
72
+ pub trait OFTFee: OFTFeeInternal + Ownable {
57
73
  #[only_auth]
58
74
  fn set_default_fee_bps(env: &Env, default_fee_bps: u64) {
59
75
  assert_with_error!(env, default_fee_bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
@@ -118,15 +134,15 @@ pub trait OFTFee: OFTFeeInternal + Ownable + Sized {
118
134
  /// Internal trait for OFT fee operations used by OFT hooks.
119
135
  /// Contains only truly internal methods that are called from OFTInner implementations.
120
136
  pub trait OFTFeeInternal {
121
- /// Calculates the amount after fee deduction (read-only, mirrors `__debit_view`).
122
- /// Used internally by `__debit_view` to calculate amount after fee.
137
+ /// Calculates the fee amount for a given transfer (read-only).
138
+ /// Used internally by `__debit_view` to calculate the fee.
123
139
  ///
124
140
  /// # Arguments
125
141
  /// * `dst_eid` - Destination endpoint ID to determine which fee rate to apply
126
142
  /// * `amount_ld` - The original amount in local decimals
127
143
  ///
128
144
  /// # Returns
129
- /// The amount after fee deduction (original amount - calculated fee)
145
+ /// The fee amount to be deducted
130
146
  fn __fee_view(env: &Env, dst_eid: u32, amount_ld: i128) -> i128 {
131
147
  // Calculate effective fee (destination-specific or default)
132
148
  let fee_bps = if OFTFeeStorage::has_fee_bps(env, dst_eid) {
@@ -135,7 +151,7 @@ pub trait OFTFeeInternal {
135
151
  OFTFeeStorage::default_fee_bps(env)
136
152
  };
137
153
  if fee_bps == 0 {
138
- return amount_ld;
154
+ return 0;
139
155
  }
140
156
  // Check that fee deposit address is set (required for fee collection)
141
157
  assert_with_error!(
@@ -143,8 +159,7 @@ pub trait OFTFeeInternal {
143
159
  OFTFeeStorage::fee_deposit_address(env).is_some(),
144
160
  OFTFeeError::InvalidFeeDepositAddress
145
161
  );
146
- let preliminary_fee = (amount_ld * fee_bps as i128) / BASE_FEE_BPS as i128;
147
- amount_ld - preliminary_fee
162
+ (amount_ld * fee_bps as i128) / BASE_FEE_BPS as i128
148
163
  }
149
164
 
150
165
  /// Charges the fee by transferring the fee amount from sender to the fee deposit address.
@@ -2,6 +2,10 @@ use common_macros::{contract_error, contract_trait, only_auth, storage};
2
2
  use soroban_sdk::{assert_with_error, contractevent, Env};
3
3
  use utils::ownable::Ownable;
4
4
 
5
+ // =========================================================================
6
+ // Storage
7
+ // =========================================================================
8
+
5
9
  #[storage]
6
10
  pub enum OFTPausableStorage {
7
11
  #[instance(bool)]
@@ -9,24 +13,35 @@ pub enum OFTPausableStorage {
9
13
  Paused,
10
14
  }
11
15
 
16
+ // =========================================================================
17
+ // Errors
18
+ // =========================================================================
19
+
12
20
  #[contract_error]
13
21
  pub enum OFTPausableError {
14
- Paused = 2300,
22
+ Paused = 3110,
15
23
  PauseStatusUnchanged,
16
24
  }
17
25
 
26
+ // =========================================================================
27
+ // Events
28
+ // =========================================================================
29
+
18
30
  #[contractevent]
19
31
  #[derive(Clone, Debug, Eq, PartialEq)]
20
32
  pub struct PausedSet {
21
33
  pub paused: bool,
22
34
  }
23
35
 
36
+ // =========================================================================
37
+ // Trait With Default Implementations
38
+ // =========================================================================
39
+
24
40
  #[contract_trait]
25
- pub trait OFTPausable: OFTPausableInternal + Ownable + Sized {
41
+ pub trait OFTPausable: OFTPausableInternal + Ownable {
26
42
  #[only_auth]
27
43
  fn set_paused(env: &Env, paused: bool) {
28
- let current_paused = OFTPausableStorage::paused(env);
29
- assert_with_error!(env, current_paused != paused, OFTPausableError::PauseStatusUnchanged);
44
+ assert_with_error!(env, Self::is_paused(env) != paused, OFTPausableError::PauseStatusUnchanged);
30
45
  OFTPausableStorage::set_paused(env, &paused);
31
46
  PausedSet { paused }.publish(env);
32
47
  }