@layerzerolabs/protocol-stellar-v2 0.2.20 → 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 (198) hide show
  1. package/.turbo/turbo-build.log +783 -802
  2. package/.turbo/turbo-lint.log +320 -157
  3. package/.turbo/turbo-test.log +1414 -1457
  4. package/Cargo.lock +109 -108
  5. package/Cargo.toml +32 -18
  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 +2 -2
  9. package/contracts/common-macros/src/lib.rs +27 -10
  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/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +6 -12
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +12 -17
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +2 -7
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +20 -9
  16. package/contracts/common-macros/src/tests/upgradeable.rs +26 -4
  17. package/contracts/common-macros/src/ttl_configurable.rs +2 -10
  18. package/contracts/common-macros/src/ttl_extendable.rs +2 -10
  19. package/contracts/common-macros/src/upgradeable.rs +56 -15
  20. package/contracts/common-macros/src/utils.rs +0 -9
  21. package/contracts/endpoint-v2/src/lib.rs +3 -2
  22. package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +2 -2
  23. package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +3 -3
  24. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +4 -4
  25. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +17 -5
  26. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
  27. package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +2 -2
  28. package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +2 -2
  29. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +6 -6
  30. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +67 -37
  31. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +5 -5
  32. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +44 -54
  33. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +7 -7
  34. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +8 -8
  35. package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +3 -3
  36. package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +4 -4
  37. package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +3 -3
  38. package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +2 -2
  39. package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +3 -3
  40. package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +2 -2
  41. package/contracts/layerzero-views/Cargo.toml +0 -1
  42. package/contracts/layerzero-views/src/layerzero_view.rs +1 -13
  43. package/contracts/macro-integration-tests/Cargo.toml +5 -15
  44. package/contracts/macro-integration-tests/tests/runtime/oapp/mod.rs +48 -0
  45. package/contracts/macro-integration-tests/tests/runtime/oapp/oapp_core.rs +170 -0
  46. package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +154 -0
  47. package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +338 -0
  48. package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +435 -0
  49. package/contracts/macro-integration-tests/tests/runtime.rs +1 -0
  50. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.rs +8 -0
  51. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.stderr +5 -0
  52. package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.rs +8 -0
  53. package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.stderr +71 -0
  54. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.rs +10 -0
  55. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.stderr +5 -0
  56. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.rs +8 -0
  57. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.stderr +5 -0
  58. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.rs +8 -0
  59. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.stderr +5 -0
  60. package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_all.rs +38 -0
  61. package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_single_trait.rs +96 -0
  62. package/contracts/macro-integration-tests/tests/ui/oapp/pass/minimal_contract.rs +64 -0
  63. package/contracts/macro-integration-tests/tests/ui/oapp/pass/struct_with_fields.rs +46 -0
  64. package/contracts/macro-integration-tests/tests/ui/ownable/fail/only_auth_missing_env.stderr +8 -0
  65. package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +1 -1
  66. package/contracts/macro-integration-tests/tests/ui/ownable/pass/only_auth_env_param_variants.rs +1 -1
  67. package/contracts/macro-integration-tests/tests/ui_oapp.rs +11 -0
  68. package/contracts/message-libs/message-lib-common/Cargo.toml +0 -1
  69. package/contracts/message-libs/message-lib-common/src/errors.rs +1 -1
  70. package/contracts/message-libs/treasury/Cargo.toml +0 -2
  71. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +2 -2
  72. package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +2 -2
  73. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +2 -2
  74. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +2 -2
  75. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +2 -2
  76. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +2 -2
  77. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +7 -27
  78. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +2 -2
  79. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +2 -2
  80. package/contracts/oapps/counter/Cargo.toml +4 -6
  81. package/contracts/oapps/counter/integration_tests/utils.rs +19 -12
  82. package/contracts/oapps/oapp/src/errors.rs +1 -1
  83. package/contracts/oapps/oapp/src/interfaces/mod.rs +3 -0
  84. package/contracts/oapps/oapp/src/interfaces/oapp_msg_inspector.rs +47 -0
  85. package/contracts/oapps/oapp/src/lib.rs +1 -0
  86. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +4 -4
  87. package/contracts/oapps/oapp/src/oapp_core.rs +5 -5
  88. package/contracts/oapps/oapp/src/oapp_options_type3.rs +12 -4
  89. package/contracts/oapps/oapp/src/oapp_receiver.rs +14 -9
  90. package/contracts/oapps/oapp/src/tests/mod.rs +4 -4
  91. package/contracts/oapps/oapp/src/tests/{test_oapp_core.rs → oapp_core.rs} +4 -4
  92. package/contracts/oapps/oapp/src/tests/{test_oapp_options_type3.rs → oapp_options_type3.rs} +3 -4
  93. package/contracts/oapps/oapp-macros/Cargo.toml +8 -4
  94. package/contracts/oapps/oapp-macros/src/generators.rs +9 -34
  95. package/contracts/oapps/oapp-macros/src/lib.rs +3 -0
  96. package/contracts/oapps/oapp-macros/src/tests/mod.rs +2 -0
  97. package/contracts/oapps/oapp-macros/src/tests/oapp.rs +88 -0
  98. package/contracts/oapps/oapp-macros/src/tests/parse_custom_impls.rs +86 -0
  99. package/contracts/oapps/oapp-macros/src/tests/snapshots/oapp_macros__tests__oapp__snapshot_generate_oapp.snap +103 -0
  100. package/contracts/oapps/oft/integration-tests/utils.rs +28 -8
  101. package/contracts/oapps/oft/src/extensions/oft_fee.rs +136 -74
  102. package/contracts/oapps/oft/src/extensions/pausable.rs +44 -10
  103. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +170 -130
  104. package/contracts/oapps/oft/src/oft.rs +19 -12
  105. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -1
  106. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +1 -1
  107. package/contracts/oapps/oft-core/Cargo.toml +1 -4
  108. package/contracts/oapps/oft-core/integration-tests/setup.rs +2 -2
  109. package/contracts/oapps/oft-core/integration-tests/utils.rs +21 -3
  110. package/contracts/oapps/oft-core/src/errors.rs +3 -2
  111. package/contracts/oapps/oft-core/src/events.rs +6 -0
  112. package/contracts/oapps/oft-core/src/lib.rs +1 -1
  113. package/contracts/oapps/oft-core/src/oft_core.rs +115 -60
  114. package/contracts/oapps/oft-core/src/storage.rs +7 -3
  115. package/contracts/oapps/oft-core/src/tests/mod.rs +1 -0
  116. package/contracts/oapps/oft-core/src/tests/test_decimals.rs +37 -2
  117. package/contracts/oapps/oft-core/src/tests/test_lz_receive.rs +2 -2
  118. package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +323 -0
  119. package/contracts/oapps/oft-core/src/tests/test_send.rs +2 -2
  120. package/contracts/oapps/oft-core/src/tests/test_utils.rs +59 -14
  121. package/contracts/utils/Cargo.toml +0 -1
  122. package/contracts/utils/src/errors.rs +1 -1
  123. package/contracts/utils/src/multisig.rs +17 -8
  124. package/contracts/utils/src/ownable.rs +6 -6
  125. package/contracts/utils/src/testing_utils.rs +124 -54
  126. package/contracts/utils/src/tests/multisig.rs +12 -12
  127. package/contracts/utils/src/tests/ownable.rs +6 -6
  128. package/contracts/utils/src/tests/testing_utils.rs +50 -167
  129. package/contracts/utils/src/tests/ttl_configurable.rs +5 -5
  130. package/contracts/utils/src/tests/upgradeable.rs +1 -1
  131. package/contracts/utils/src/ttl_configurable.rs +10 -4
  132. package/contracts/utils/src/upgradeable.rs +5 -5
  133. package/contracts/workers/dvn/Cargo.toml +5 -6
  134. package/contracts/workers/dvn/src/dvn.rs +2 -12
  135. package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
  136. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +37 -19
  137. package/contracts/workers/dvn-fee-lib/src/lib.rs +12 -2
  138. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +15 -13
  139. package/contracts/workers/executor/Cargo.toml +3 -0
  140. package/contracts/workers/executor/src/executor.rs +2 -12
  141. package/contracts/workers/executor/src/lib.rs +2 -2
  142. package/contracts/workers/executor/src/tests/auth.rs +394 -0
  143. package/contracts/workers/executor/src/tests/executor.rs +410 -0
  144. package/contracts/workers/executor/src/tests/mod.rs +3 -0
  145. package/contracts/workers/executor/src/tests/setup.rs +250 -0
  146. package/contracts/workers/executor-fee-lib/Cargo.toml +5 -0
  147. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +1 -12
  148. package/contracts/workers/executor-fee-lib/src/lib.rs +8 -2
  149. package/contracts/workers/executor-helper/Cargo.toml +0 -1
  150. package/contracts/workers/price-feed/Cargo.toml +5 -0
  151. package/contracts/workers/price-feed/src/lib.rs +9 -4
  152. package/contracts/workers/price-feed/src/price_feed.rs +1 -11
  153. package/contracts/workers/worker/src/errors.rs +1 -1
  154. package/contracts/workers/worker/src/tests/setup.rs +1 -1
  155. package/contracts/workers/worker/src/tests/worker.rs +55 -41
  156. package/contracts/workers/worker/src/worker.rs +34 -25
  157. package/docs/error-spec.md +55 -0
  158. package/docs/layerzero-v2-on-stellar.md +447 -0
  159. package/docs/oapp-guide.md +212 -0
  160. package/docs/oft-guide.md +314 -0
  161. package/package.json +3 -3
  162. package/sdk/.turbo/turbo-test.log +260 -257
  163. package/sdk/dist/generated/bml.d.ts +3 -3
  164. package/sdk/dist/generated/bml.js +4 -4
  165. package/sdk/dist/generated/counter.d.ts +295 -295
  166. package/sdk/dist/generated/counter.js +43 -43
  167. package/sdk/dist/generated/dvn.d.ts +91 -91
  168. package/sdk/dist/generated/dvn.js +24 -24
  169. package/sdk/dist/generated/dvn_fee_lib.d.ts +92 -92
  170. package/sdk/dist/generated/dvn_fee_lib.js +25 -25
  171. package/sdk/dist/generated/endpoint.d.ts +99 -99
  172. package/sdk/dist/generated/endpoint.js +16 -16
  173. package/sdk/dist/generated/executor.d.ts +91 -91
  174. package/sdk/dist/generated/executor.js +24 -24
  175. package/sdk/dist/generated/executor_fee_lib.d.ts +92 -92
  176. package/sdk/dist/generated/executor_fee_lib.js +25 -25
  177. package/sdk/dist/generated/executor_helper.d.ts +3 -3
  178. package/sdk/dist/generated/executor_helper.js +4 -4
  179. package/sdk/dist/generated/layerzero_view.d.ts +186 -186
  180. package/sdk/dist/generated/layerzero_view.js +35 -35
  181. package/sdk/dist/generated/oft.d.ts +366 -352
  182. package/sdk/dist/generated/oft.js +74 -79
  183. package/sdk/dist/generated/price_feed.d.ts +198 -198
  184. package/sdk/dist/generated/price_feed.js +39 -39
  185. package/sdk/dist/generated/sml.d.ts +99 -99
  186. package/sdk/dist/generated/sml.js +16 -16
  187. package/sdk/dist/generated/treasury.d.ts +99 -99
  188. package/sdk/dist/generated/treasury.js +16 -16
  189. package/sdk/dist/generated/uln302.d.ts +99 -99
  190. package/sdk/dist/generated/uln302.js +16 -16
  191. package/sdk/dist/generated/upgrader.d.ts +3 -3
  192. package/sdk/dist/generated/upgrader.js +3 -3
  193. package/sdk/package.json +1 -1
  194. package/sdk/test/suites/localnet.ts +84 -20
  195. package/contracts/ERROR_SPEC.md +0 -51
  196. package/contracts/endpoint-v2/ARCHITECTURE.md +0 -233
  197. /package/contracts/oapps/oapp/src/tests/{test_oapp_receiver.rs → oapp_receiver.rs} +0 -0
  198. /package/contracts/oapps/oapp/src/tests/{test_oapp_sender.rs → oapp_sender.rs} +0 -0
@@ -0,0 +1,435 @@
1
+ // Runtime tests: OAppSenderInternal defaults generated by `#[oapp]`.
2
+
3
+ use endpoint_v2::{MessagingFee, MessagingParams, MessagingReceipt, Origin};
4
+ use oapp::errors::OAppError;
5
+ use oapp::oapp_receiver::LzReceiveInternal;
6
+ use oapp_macros::oapp;
7
+ use soroban_sdk::{
8
+ contract, contractimpl, symbol_short,
9
+ testutils::{Address as _, MockAuth, MockAuthInvoke},
10
+ token::{StellarAssetClient, TokenClient},
11
+ Address, Bytes, BytesN, Env, IntoVal,
12
+ };
13
+
14
+ const REMOTE_EID: u32 = 100;
15
+ const UNSET_EID: u32 = 999;
16
+
17
+ // Mock Endpoint contract (subset used by sender internals).
18
+ #[contract]
19
+ pub struct MockEndpoint;
20
+
21
+ #[contractimpl]
22
+ impl MockEndpoint {
23
+ pub fn __constructor(env: Env, zro_token: Address, native_token: Address) {
24
+ env.storage().instance().set(&symbol_short!("zro"), &Some(zro_token));
25
+ env.storage().instance().set(&symbol_short!("ntk"), &native_token);
26
+ }
27
+
28
+ pub fn set_delegate(_env: Env, _oapp: Address, _delegate: Option<Address>) {
29
+ // no-op
30
+ }
31
+
32
+ pub fn quote(env: Env, sender: Address, params: MessagingParams) -> MessagingFee {
33
+ env.storage().instance().set(&symbol_short!("qts"), &sender);
34
+ env.storage().instance().set(&symbol_short!("qtp"), &params);
35
+ MessagingFee { native_fee: 1000, zro_fee: if params.pay_in_zro { 500 } else { 0 } }
36
+ }
37
+
38
+ pub fn send(env: Env, sender: Address, params: MessagingParams, refund_address: Address) -> MessagingReceipt {
39
+ env.storage().instance().set(&symbol_short!("snds"), &sender);
40
+ env.storage().instance().set(&symbol_short!("sndp"), &params);
41
+ env.storage().instance().set(&symbol_short!("sndr"), &refund_address);
42
+ MessagingReceipt {
43
+ guid: BytesN::from_array(&env, &[1u8; 32]),
44
+ nonce: 1,
45
+ fee: MessagingFee { native_fee: 1000, zro_fee: if params.pay_in_zro { 500 } else { 0 } },
46
+ }
47
+ }
48
+
49
+ pub fn last_send(env: Env) -> (Address, MessagingParams, Address) {
50
+ (
51
+ env.storage().instance().get(&symbol_short!("snds")).unwrap(),
52
+ env.storage().instance().get(&symbol_short!("sndp")).unwrap(),
53
+ env.storage().instance().get(&symbol_short!("sndr")).unwrap(),
54
+ )
55
+ }
56
+
57
+ pub fn last_quote(env: Env) -> (Address, MessagingParams) {
58
+ (
59
+ env.storage().instance().get(&symbol_short!("qts")).unwrap(),
60
+ env.storage().instance().get(&symbol_short!("qtp")).unwrap(),
61
+ )
62
+ }
63
+
64
+ pub fn zro(env: Env) -> Option<Address> {
65
+ env.storage().instance().get(&symbol_short!("zro")).unwrap_or(None)
66
+ }
67
+
68
+ pub fn native_token(env: Env) -> Address {
69
+ env.storage().instance().get(&symbol_short!("ntk")).unwrap()
70
+ }
71
+
72
+ pub fn set_zro(env: Env, zro: Option<Address>) {
73
+ env.storage().instance().set(&symbol_short!("zro"), &zro);
74
+ }
75
+ }
76
+
77
+ #[oapp]
78
+ pub struct TestOAppSender;
79
+
80
+ impl LzReceiveInternal for TestOAppSender {
81
+ fn __lz_receive(
82
+ _env: &Env,
83
+ _origin: &Origin,
84
+ _guid: &BytesN<32>,
85
+ _message: &Bytes,
86
+ _extra_data: &Bytes,
87
+ _executor: &Address,
88
+ _value: i128,
89
+ ) {
90
+ }
91
+ }
92
+
93
+ #[contractimpl]
94
+ impl TestOAppSender {
95
+ pub fn init(env: Env, owner: Address, endpoint: Address) {
96
+ oapp::oapp_core::initialize_oapp::<Self>(&env, &owner, &endpoint, &None::<Address>);
97
+ }
98
+
99
+ pub fn quote(env: &Env, dst_eid: u32, message: &Bytes, options: &Bytes, pay_in_zro: bool) -> MessagingFee {
100
+ Self::__quote(env, dst_eid, message, options, pay_in_zro)
101
+ }
102
+
103
+ pub fn send(
104
+ env: &Env,
105
+ sender: &Address,
106
+ dst_eid: u32,
107
+ message: &Bytes,
108
+ options: &Bytes,
109
+ fee: &MessagingFee,
110
+ refund_address: &Address,
111
+ ) -> MessagingReceipt {
112
+ sender.require_auth();
113
+ Self::__lz_send(env, dst_eid, message, options, sender, fee, refund_address)
114
+ }
115
+ }
116
+
117
+ fn set_peer(
118
+ env: &Env,
119
+ owner: &Address,
120
+ oapp: &Address,
121
+ client: &TestOAppSenderClient<'_>,
122
+ eid: u32,
123
+ peer: &BytesN<32>,
124
+ ) {
125
+ let peer_opt = Some(peer.clone());
126
+ env.mock_auths(&[MockAuth {
127
+ address: owner,
128
+ invoke: &MockAuthInvoke {
129
+ contract: oapp,
130
+ fn_name: "set_peer",
131
+ args: (&eid, &peer_opt).into_val(env),
132
+ sub_invokes: &[],
133
+ },
134
+ }]);
135
+ client.set_peer(&eid, &peer_opt);
136
+ }
137
+
138
+ fn mint_to(
139
+ env: &Env,
140
+ token_admin: &Address,
141
+ token: &Address,
142
+ token_admin_client: &StellarAssetClient<'_>,
143
+ to: &Address,
144
+ amount: i128,
145
+ ) {
146
+ env.mock_auths(&[MockAuth {
147
+ address: token_admin,
148
+ invoke: &MockAuthInvoke {
149
+ contract: token,
150
+ fn_name: "mint",
151
+ args: (to, amount).into_val(env),
152
+ sub_invokes: &[],
153
+ },
154
+ }]);
155
+ token_admin_client.mint(to, &amount);
156
+ }
157
+
158
+ struct Setup {
159
+ env: Env,
160
+ owner: Address,
161
+ token_admin: Address,
162
+
163
+ native_token: Address,
164
+ zro_token: Address,
165
+
166
+ endpoint: Address,
167
+ oapp: Address,
168
+ }
169
+
170
+ impl Setup {
171
+ fn oapp_client(&self) -> TestOAppSenderClient<'_> {
172
+ TestOAppSenderClient::new(&self.env, &self.oapp)
173
+ }
174
+
175
+ fn endpoint_client(&self) -> MockEndpointClient<'_> {
176
+ MockEndpointClient::new(&self.env, &self.endpoint)
177
+ }
178
+
179
+ fn native_token_client(&self) -> TokenClient<'_> {
180
+ TokenClient::new(&self.env, &self.native_token)
181
+ }
182
+
183
+ fn native_token_admin_client(&self) -> StellarAssetClient<'_> {
184
+ StellarAssetClient::new(&self.env, &self.native_token)
185
+ }
186
+
187
+ fn zro_token_client(&self) -> TokenClient<'_> {
188
+ TokenClient::new(&self.env, &self.zro_token)
189
+ }
190
+
191
+ fn zro_token_admin_client(&self) -> StellarAssetClient<'_> {
192
+ StellarAssetClient::new(&self.env, &self.zro_token)
193
+ }
194
+ }
195
+
196
+ fn setup() -> Setup {
197
+ let env = Env::default();
198
+ let owner = Address::generate(&env);
199
+ let token_admin = Address::generate(&env);
200
+
201
+ let native_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
202
+ let native_token = native_token_sac.address();
203
+
204
+ let zro_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
205
+ let zro_token = zro_token_sac.address();
206
+
207
+ let endpoint = env.register(MockEndpoint, (&zro_token, &native_token));
208
+
209
+ let oapp = env.register(TestOAppSender, ());
210
+ let client = TestOAppSenderClient::new(&env, &oapp);
211
+ client.init(&owner, &endpoint);
212
+
213
+ Setup { env, owner, token_admin, native_token, zro_token, endpoint, oapp }
214
+ }
215
+
216
+ #[test]
217
+ fn quote_with_peer_set_works_and_no_peer_errors() {
218
+ let context = setup();
219
+ let env = &context.env;
220
+ let client = context.oapp_client();
221
+
222
+ let peer = BytesN::from_array(env, &[1u8; 32]);
223
+ set_peer(env, &context.owner, &context.oapp, &client, REMOTE_EID, &peer);
224
+
225
+ let message = Bytes::from_array(env, &[1, 2, 3]);
226
+ let options = Bytes::new(env);
227
+
228
+ let fee = client.quote(&REMOTE_EID, &message, &options, &false);
229
+ assert_eq!(fee.native_fee, 1000);
230
+ assert_eq!(fee.zro_fee, 0);
231
+
232
+ let (quote_sender, quote_params) = context.endpoint_client().last_quote();
233
+ assert_eq!(quote_sender, context.oapp);
234
+ assert_eq!(quote_params.dst_eid, REMOTE_EID);
235
+ assert_eq!(quote_params.receiver, peer);
236
+ assert_eq!(quote_params.message, message);
237
+ assert_eq!(quote_params.options, options);
238
+ assert_eq!(quote_params.pay_in_zro, false);
239
+
240
+ let fee_zro = client.quote(&REMOTE_EID, &message, &options, &true);
241
+ assert_eq!(fee_zro.native_fee, 1000);
242
+ assert_eq!(fee_zro.zro_fee, 500);
243
+
244
+ let (_quote_sender, quote_params) = context.endpoint_client().last_quote();
245
+ assert_eq!(quote_params.pay_in_zro, true);
246
+
247
+ // No peer configured for UNSET_EID => error
248
+ let no_peer = client.try_quote(&UNSET_EID, &message, &options, &false);
249
+ assert_eq!(no_peer.err().unwrap().ok().unwrap(), OAppError::NoPeer.into());
250
+ }
251
+
252
+ #[test]
253
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
254
+ fn lz_send_requires_sender_auth() {
255
+ let context = setup();
256
+ let env = &context.env;
257
+ let client = context.oapp_client();
258
+
259
+ // No env.mock_auths for sender => should panic at sender.require_auth().
260
+ let sender = Address::generate(env);
261
+ let fee = MessagingFee { native_fee: 0, zro_fee: 0 };
262
+ let message = Bytes::new(env);
263
+ let options = Bytes::new(env);
264
+ let refund = Address::generate(env);
265
+ client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund);
266
+ }
267
+
268
+ #[test]
269
+ fn lz_send_pays_native_and_zro_and_calls_endpoint_send() {
270
+ let context = setup();
271
+ let env = &context.env;
272
+ let client = context.oapp_client();
273
+
274
+ let peer = BytesN::from_array(env, &[2u8; 32]);
275
+ set_peer(env, &context.owner, &context.oapp, &client, REMOTE_EID, &peer);
276
+
277
+ let sender = Address::generate(env);
278
+ let fee = MessagingFee { native_fee: 1000, zro_fee: 500 };
279
+ mint_to(
280
+ env,
281
+ &context.token_admin,
282
+ &context.native_token,
283
+ &context.native_token_admin_client(),
284
+ &sender,
285
+ fee.native_fee,
286
+ );
287
+ mint_to(env, &context.token_admin, &context.zro_token, &context.zro_token_admin_client(), &sender, fee.zro_fee);
288
+
289
+ let message = Bytes::from_array(env, &[9, 9, 9]);
290
+ let options = Bytes::from_array(env, &[7]);
291
+ let refund = Address::generate(env);
292
+
293
+ // send() requires sender auth and will sub-invoke token transfers.
294
+ let native_transfer = MockAuthInvoke {
295
+ contract: &context.native_token,
296
+ fn_name: "transfer",
297
+ args: (&sender, &context.endpoint, &fee.native_fee).into_val(env),
298
+ sub_invokes: &[],
299
+ };
300
+ let zro_transfer = MockAuthInvoke {
301
+ contract: &context.zro_token,
302
+ fn_name: "transfer",
303
+ args: (&sender, &context.endpoint, &fee.zro_fee).into_val(env),
304
+ sub_invokes: &[],
305
+ };
306
+ env.mock_auths(&[MockAuth {
307
+ address: &sender,
308
+ invoke: &MockAuthInvoke {
309
+ contract: &context.oapp,
310
+ fn_name: "send",
311
+ args: (&sender, &REMOTE_EID, &message, &options, &fee, &refund).into_val(env),
312
+ sub_invokes: &[native_transfer, zro_transfer],
313
+ },
314
+ }]);
315
+
316
+ let receipt = client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund);
317
+ assert_eq!(receipt.nonce, 1);
318
+ assert_eq!(receipt.fee.native_fee, 1000);
319
+ assert_eq!(receipt.fee.zro_fee, 500);
320
+
321
+ let (endpoint_sender, params, got_refund) = context.endpoint_client().last_send();
322
+ assert_eq!(endpoint_sender, context.oapp);
323
+ assert_eq!(params.dst_eid, REMOTE_EID);
324
+ assert_eq!(params.receiver, peer);
325
+ assert_eq!(params.message, message);
326
+ assert_eq!(params.options, options);
327
+ assert_eq!(params.pay_in_zro, true);
328
+ assert_eq!(got_refund, refund);
329
+
330
+ let native_token_client = context.native_token_client();
331
+ let zro_token_client = context.zro_token_client();
332
+ assert_eq!(native_token_client.balance(&sender), 0);
333
+ assert_eq!(native_token_client.balance(&context.endpoint), 1000);
334
+ assert_eq!(zro_token_client.balance(&sender), 0);
335
+ assert_eq!(zro_token_client.balance(&context.endpoint), 500);
336
+ }
337
+
338
+ #[test]
339
+ fn lz_send_native_only_does_not_pay_zro() {
340
+ let context = setup();
341
+ let env = &context.env;
342
+ let client = context.oapp_client();
343
+
344
+ let peer = BytesN::from_array(env, &[3u8; 32]);
345
+ set_peer(env, &context.owner, &context.oapp, &client, REMOTE_EID, &peer);
346
+
347
+ let sender = Address::generate(env);
348
+ let fee = MessagingFee { native_fee: 1000, zro_fee: 0 };
349
+ mint_to(
350
+ env,
351
+ &context.token_admin,
352
+ &context.native_token,
353
+ &context.native_token_admin_client(),
354
+ &sender,
355
+ fee.native_fee,
356
+ );
357
+ mint_to(env, &context.token_admin, &context.zro_token, &context.zro_token_admin_client(), &sender, 100);
358
+
359
+ let message = Bytes::from_array(env, &[1, 2, 3]);
360
+ let options = Bytes::new(env);
361
+ let refund = Address::generate(env);
362
+
363
+ let native_transfer = MockAuthInvoke {
364
+ contract: &context.native_token,
365
+ fn_name: "transfer",
366
+ args: (&sender, &context.endpoint, &fee.native_fee).into_val(env),
367
+ sub_invokes: &[],
368
+ };
369
+ env.mock_auths(&[MockAuth {
370
+ address: &sender,
371
+ invoke: &MockAuthInvoke {
372
+ contract: &context.oapp,
373
+ fn_name: "send",
374
+ args: (&sender, &REMOTE_EID, &message, &options, &fee, &refund).into_val(env),
375
+ sub_invokes: &[native_transfer],
376
+ },
377
+ }]);
378
+
379
+ let receipt = client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund);
380
+ assert_eq!(receipt.fee.native_fee, 1000);
381
+ assert_eq!(receipt.fee.zro_fee, 0);
382
+
383
+ let (_endpoint_sender, params, _refund) = context.endpoint_client().last_send();
384
+ assert_eq!(params.pay_in_zro, false);
385
+
386
+ let native_token_client = context.native_token_client();
387
+ let zro_token_client = context.zro_token_client();
388
+ assert_eq!(native_token_client.balance(&sender), 0);
389
+ assert_eq!(native_token_client.balance(&context.endpoint), 1000);
390
+ assert_eq!(zro_token_client.balance(&context.endpoint), 0);
391
+ assert_eq!(zro_token_client.balance(&sender), 100);
392
+ }
393
+
394
+ #[test]
395
+ fn pay_zro_unavailable_returns_error() {
396
+ let context = setup();
397
+ let env = &context.env;
398
+ let client = context.oapp_client();
399
+ context.endpoint_client().set_zro(&None);
400
+
401
+ let sender = Address::generate(env);
402
+ let fee = MessagingFee { native_fee: 1000, zro_fee: 500 };
403
+ mint_to(
404
+ env,
405
+ &context.token_admin,
406
+ &context.native_token,
407
+ &context.native_token_admin_client(),
408
+ &sender,
409
+ fee.native_fee,
410
+ );
411
+
412
+ let message = Bytes::from_array(env, &[1, 2, 3]);
413
+ let options = Bytes::new(env);
414
+ let refund = Address::generate(env);
415
+
416
+ // send() requires sender auth and will sub-invoke native fee transfer.
417
+ let native_transfer = MockAuthInvoke {
418
+ contract: &context.native_token,
419
+ fn_name: "transfer",
420
+ args: (&sender, &context.endpoint, &fee.native_fee).into_val(env),
421
+ sub_invokes: &[],
422
+ };
423
+ env.mock_auths(&[MockAuth {
424
+ address: &sender,
425
+ invoke: &MockAuthInvoke {
426
+ contract: &context.oapp,
427
+ fn_name: "send",
428
+ args: (&sender, &REMOTE_EID, &message, &options, &fee, &refund).into_val(env),
429
+ sub_invokes: &[native_transfer],
430
+ },
431
+ }]);
432
+
433
+ let result = client.try_send(&sender, &REMOTE_EID, &message, &options, &fee, &refund);
434
+ assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::ZroTokenUnavailable.into());
435
+ }
@@ -1,4 +1,5 @@
1
1
  mod runtime {
2
+ mod oapp;
2
3
  mod ownable;
3
4
  mod storage;
4
5
  mod ttl_configurable;
@@ -0,0 +1,8 @@
1
+ // UI (trybuild) negative test: `custom` must be a bracketed list.
2
+
3
+ use oapp_macros::oapp;
4
+
5
+ #[oapp(custom = core)]
6
+ pub struct MyOApp;
7
+
8
+ fn main() {}
@@ -0,0 +1,5 @@
1
+ error: expected square brackets
2
+ --> tests/ui/oapp/fail/custom_wrong_value.rs:5:17
3
+ |
4
+ 5 | #[oapp(custom = core)]
5
+ | ^^^^
@@ -0,0 +1,8 @@
1
+ // UI (trybuild) negative test: `#[oapp]` requires `LzReceiveInternal` to be implemented.
2
+
3
+ use oapp_macros::oapp;
4
+
5
+ #[oapp]
6
+ pub struct MyOApp;
7
+
8
+ fn main() {}
@@ -0,0 +1,71 @@
1
+ error[E0277]: the trait bound `MyOApp: LzReceiveInternal` is not satisfied
2
+ --> tests/ui/oapp/fail/missing_lz_receive_internal.rs:6:12
3
+ |
4
+ 6 | pub struct MyOApp;
5
+ | ^^^^^^ the trait `LzReceiveInternal` is not implemented for `MyOApp`
6
+ |
7
+ note: required by a bound in `OAppReceiver`
8
+ --> $WORKSPACE/contracts/oapps/oapp/src/oapp_receiver.rs
9
+ |
10
+ | pub trait OAppReceiver: OAppCore + LzReceiveInternal {
11
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `OAppReceiver`
12
+
13
+ error[E0277]: the trait bound `MyOApp: LzReceiveInternal` is not satisfied
14
+ --> tests/ui/oapp/fail/missing_lz_receive_internal.rs:6:12
15
+ |
16
+ 6 | pub struct MyOApp;
17
+ | ^^^^^^ the trait `LzReceiveInternal` is not implemented for `MyOApp`
18
+ |
19
+ note: required by a bound in `oapp::oapp_receiver::OAppReceiver::allow_initialize_path`
20
+ --> $WORKSPACE/contracts/oapps/oapp/src/oapp_receiver.rs
21
+ |
22
+ | pub trait OAppReceiver: OAppCore + LzReceiveInternal {
23
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `OAppReceiver::allow_initialize_path`
24
+ ...
25
+ | fn allow_initialize_path(env: &soroban_sdk::Env, origin: &endpoint_v2::Origin) -> bool {
26
+ | --------------------- required by a bound in this associated function
27
+
28
+ error[E0277]: the trait bound `MyOApp: LzReceiveInternal` is not satisfied
29
+ --> tests/ui/oapp/fail/missing_lz_receive_internal.rs:6:12
30
+ |
31
+ 6 | pub struct MyOApp;
32
+ | ^^^^^^ the trait `LzReceiveInternal` is not implemented for `MyOApp`
33
+ |
34
+ note: required by a bound in `oapp::oapp_receiver::OAppReceiver::next_nonce`
35
+ --> $WORKSPACE/contracts/oapps/oapp/src/oapp_receiver.rs
36
+ |
37
+ | pub trait OAppReceiver: OAppCore + LzReceiveInternal {
38
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `OAppReceiver::next_nonce`
39
+ ...
40
+ | fn next_nonce(_env: &soroban_sdk::Env, _src_eid: u32, _sender: &soroban_sdk::BytesN<32>) -> u64 {
41
+ | ---------- required by a bound in this associated function
42
+
43
+ error[E0277]: the trait bound `MyOApp: LzReceiveInternal` is not satisfied
44
+ --> tests/ui/oapp/fail/missing_lz_receive_internal.rs:6:12
45
+ |
46
+ 6 | pub struct MyOApp;
47
+ | ^^^^^^ the trait `LzReceiveInternal` is not implemented for `MyOApp`
48
+ |
49
+ note: required by a bound in `oapp::oapp_receiver::OAppReceiver::lz_receive`
50
+ --> $WORKSPACE/contracts/oapps/oapp/src/oapp_receiver.rs
51
+ |
52
+ | pub trait OAppReceiver: OAppCore + LzReceiveInternal {
53
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `OAppReceiver::lz_receive`
54
+ ...
55
+ | fn lz_receive(
56
+ | ---------- required by a bound in this associated function
57
+
58
+ error[E0277]: the trait bound `MyOApp: LzReceiveInternal` is not satisfied
59
+ --> tests/ui/oapp/fail/missing_lz_receive_internal.rs:6:12
60
+ |
61
+ 6 | pub struct MyOApp;
62
+ | ^^^^^^ the trait `LzReceiveInternal` is not implemented for `MyOApp`
63
+ |
64
+ note: required by a bound in `is_compose_msg_sender`
65
+ --> $WORKSPACE/contracts/oapps/oapp/src/oapp_receiver.rs
66
+ |
67
+ | pub trait OAppReceiver: OAppCore + LzReceiveInternal {
68
+ | ^^^^^^^^^^^^^^^^^ required by this bound in `OAppReceiver::is_compose_msg_sender`
69
+ ...
70
+ | fn is_compose_msg_sender(
71
+ | --------------------- required by a bound in this associated function
@@ -0,0 +1,10 @@
1
+ // UI (trybuild) negative test: `#[oapp]` must be applied to a struct.
2
+
3
+ use oapp_macros::oapp;
4
+
5
+ #[oapp]
6
+ pub enum NotAStruct {
7
+ A,
8
+ }
9
+
10
+ fn main() {}
@@ -0,0 +1,5 @@
1
+ error: expected `struct`
2
+ --> tests/ui/oapp/fail/non_struct_input.rs:6:5
3
+ |
4
+ 6 | pub enum NotAStruct {
5
+ | ^^^^
@@ -0,0 +1,8 @@
1
+ // UI (trybuild) negative test: unknown `custom` option is rejected.
2
+
3
+ use oapp_macros::oapp;
4
+
5
+ #[oapp(custom = [core, not_a_real_option])]
6
+ pub struct MyOApp;
7
+
8
+ fn main() {}
@@ -0,0 +1,5 @@
1
+ error: expected one of `core`, `sender`, `receiver`, `options_type3`
2
+ --> tests/ui/oapp/fail/unknown_custom_option.rs:5:24
3
+ |
4
+ 5 | #[oapp(custom = [core, not_a_real_option])]
5
+ | ^^^^^^^^^^^^^^^^^
@@ -0,0 +1,8 @@
1
+ // UI (trybuild) negative test: only `custom = [...]` is accepted.
2
+
3
+ use oapp_macros::oapp;
4
+
5
+ #[oapp(nope = [core])]
6
+ pub struct MyOApp;
7
+
8
+ fn main() {}
@@ -0,0 +1,5 @@
1
+ error: expected `custom`
2
+ --> tests/ui/oapp/fail/wrong_key.rs:5:8
3
+ |
4
+ 5 | #[oapp(nope = [core])]
5
+ | ^^^^
@@ -0,0 +1,38 @@
1
+ // UI (trybuild) test: `#[oapp(custom = [core, sender, receiver, options_type3])]` works.
2
+
3
+ use endpoint_v2::Origin;
4
+ use oapp::oapp_core::OAppCore;
5
+ use oapp::oapp_options_type3::OAppOptionsType3;
6
+ use oapp::oapp_receiver::{LzReceiveInternal, OAppReceiver};
7
+ use oapp::oapp_sender::OAppSenderInternal;
8
+ use oapp_macros::oapp;
9
+ use soroban_sdk::{contractimpl, Address, Bytes, BytesN, Env};
10
+
11
+ #[oapp(custom = [core, sender, receiver, options_type3])]
12
+ pub struct MyOApp;
13
+
14
+ impl LzReceiveInternal for MyOApp {
15
+ fn __lz_receive(
16
+ _env: &Env,
17
+ _origin: &Origin,
18
+ _guid: &BytesN<32>,
19
+ _message: &Bytes,
20
+ _extra_data: &Bytes,
21
+ _executor: &Address,
22
+ _value: i128,
23
+ ) {
24
+ }
25
+ }
26
+
27
+ #[contractimpl(contracttrait)]
28
+ impl OAppCore for MyOApp {}
29
+
30
+ impl OAppSenderInternal for MyOApp {}
31
+
32
+ #[contractimpl(contracttrait)]
33
+ impl OAppReceiver for MyOApp {}
34
+
35
+ #[contractimpl(contracttrait)]
36
+ impl OAppOptionsType3 for MyOApp {}
37
+
38
+ fn main() {}