@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,10 +1,11 @@
1
- use crate::{
2
- self as oapp, errors::OAppError, oapp_core::OAppCoreStorage, oapp_receiver::LzReceiveInternal,
3
- tests::test_oapp_core::DummyEndpoint,
4
- };
1
+ use crate::{self as oapp, errors::OAppError, oapp_receiver::LzReceiveInternal};
5
2
  use endpoint_v2::Origin;
6
- use soroban_sdk::{assert_with_error, contractimpl, testutils::Address as _, Address, Bytes, BytesN, Env};
7
- use utils::option_ext::OptionExt;
3
+ use soroban_sdk::{
4
+ contract, contractimpl, symbol_short,
5
+ testutils::{Address as _, MockAuth, MockAuthInvoke},
6
+ token::StellarAssetClient,
7
+ Address, Bytes, BytesN, Env, IntoVal,
8
+ };
8
9
 
9
10
  #[oapp_macros::oapp]
10
11
  pub struct DummyOAppReceiver;
@@ -28,24 +29,57 @@ impl DummyOAppReceiver {
28
29
  pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address) {
29
30
  oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, &None);
30
31
  }
31
-
32
- pub fn assert_allowed_peer(env: &Env, origin: &Origin) {
33
- let peer = OAppCoreStorage::peer(env, origin.src_eid).unwrap_or_panic(env, OAppError::NoPeer);
34
- assert_with_error!(env, peer == origin.sender, OAppError::OnlyPeer);
35
- }
36
32
  }
37
33
 
38
34
  const REMOTE_EID: u32 = 100;
39
35
  const UNSET_EID: u32 = 999;
40
36
 
37
+ // Mock Endpoint (minimal subset used by oapp_receiver::verify_and_clear_payload)
38
+
39
+ #[contract]
40
+ pub struct MockEndpoint;
41
+
42
+ #[contractimpl]
43
+ impl MockEndpoint {
44
+ pub fn __constructor(env: Env, native_token: Address) {
45
+ env.storage().instance().set(&symbol_short!("ntk"), &native_token);
46
+ }
47
+
48
+ pub fn set_delegate(_env: Env, _oapp: &Address, _delegate: &Option<Address>) {
49
+ // do nothing
50
+ }
51
+
52
+ pub fn native_token(env: Env) -> Address {
53
+ env.storage().instance().get(&symbol_short!("ntk")).unwrap()
54
+ }
55
+
56
+ pub fn clear(env: Env, caller: Address, origin: Origin, receiver: Address, guid: BytesN<32>, message: Bytes) {
57
+ // Record last clear for assertions
58
+ env.storage().instance().set(&symbol_short!("clr_c"), &caller);
59
+ env.storage().instance().set(&symbol_short!("clr_o"), &origin);
60
+ env.storage().instance().set(&symbol_short!("clr_r"), &receiver);
61
+ env.storage().instance().set(&symbol_short!("clr_g"), &guid);
62
+ env.storage().instance().set(&symbol_short!("clr_m"), &message);
63
+ }
64
+
65
+ pub fn last_clear(env: Env) -> (Address, Origin, Address, BytesN<32>, Bytes) {
66
+ (
67
+ env.storage().instance().get(&symbol_short!("clr_c")).unwrap(),
68
+ env.storage().instance().get(&symbol_short!("clr_o")).unwrap(),
69
+ env.storage().instance().get(&symbol_short!("clr_r")).unwrap(),
70
+ env.storage().instance().get(&symbol_short!("clr_g")).unwrap(),
71
+ env.storage().instance().get(&symbol_short!("clr_m")).unwrap(),
72
+ )
73
+ }
74
+ }
75
+
41
76
  struct TestSetup<'a> {
42
77
  env: Env,
43
- #[allow(dead_code)]
44
78
  owner: Address,
45
- #[allow(dead_code)]
46
79
  endpoint: Address,
47
- #[allow(dead_code)]
80
+ token_admin: Address,
48
81
  native_token: Address,
82
+ native_token_admin_client: StellarAssetClient<'a>,
49
83
  oapp_client: DummyOAppReceiverClient<'a>,
50
84
  }
51
85
 
@@ -53,15 +87,56 @@ fn setup<'a>() -> TestSetup<'a> {
53
87
  let env = Env::default();
54
88
 
55
89
  let owner = Address::generate(&env);
56
- let endpoint = env.register(DummyEndpoint, ());
57
- let native_token = Address::generate(&env);
90
+ let token_admin = Address::generate(&env);
91
+ let native_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
92
+ let native_token = native_token_sac.address();
93
+ let native_token_admin_client = StellarAssetClient::new(&env, &native_token);
94
+
95
+ let endpoint = env.register(MockEndpoint, (&native_token,));
58
96
  let oapp = env.register(DummyOAppReceiver, (&owner, &endpoint));
59
97
  let oapp_client = DummyOAppReceiverClient::new(&env, &oapp);
60
- TestSetup { env, owner, endpoint, native_token, oapp_client }
98
+ TestSetup { env, owner, endpoint, token_admin, native_token, native_token_admin_client, oapp_client }
99
+ }
100
+
101
+ fn set_peer(env: &Env, owner: &Address, oapp_client: &DummyOAppReceiverClient<'_>, eid: u32, peer: &BytesN<32>) {
102
+ let peer_option = Some(peer.clone());
103
+ env.mock_auths(&[MockAuth {
104
+ address: owner,
105
+ invoke: &MockAuthInvoke {
106
+ contract: &oapp_client.address,
107
+ fn_name: "set_peer",
108
+ args: (&eid, &peer_option).into_val(env),
109
+ sub_invokes: &[],
110
+ },
111
+ }]);
112
+ oapp_client.set_peer(&eid, &peer_option);
113
+ }
114
+
115
+ fn lz_receive(
116
+ env: &Env,
117
+ oapp_client: &DummyOAppReceiverClient<'_>,
118
+ executor: &Address,
119
+ origin: &Origin,
120
+ guid: &BytesN<32>,
121
+ message: &Bytes,
122
+ extra_data: &Bytes,
123
+ value: i128,
124
+ sub_invokes: &[MockAuthInvoke<'_>],
125
+ ) {
126
+ env.mock_auths(&[MockAuth {
127
+ address: executor,
128
+ invoke: &MockAuthInvoke {
129
+ contract: &oapp_client.address,
130
+ fn_name: "lz_receive",
131
+ args: (executor, origin, guid, message, extra_data, value).into_val(env),
132
+ sub_invokes,
133
+ },
134
+ }]);
135
+ oapp_client.lz_receive(executor, origin, guid, message, extra_data, &value);
61
136
  }
62
137
 
63
138
  #[test]
64
- fn test_is_compose_msg_sender_same_contract() {
139
+ fn test_is_compose_msg_sender() {
65
140
  let TestSetup { env, oapp_client, .. } = setup();
66
141
 
67
142
  let origin = Origin { src_eid: REMOTE_EID, sender: BytesN::from_array(&env, &[1; 32]), nonce: 1 };
@@ -70,84 +145,237 @@ fn test_is_compose_msg_sender_same_contract() {
70
145
  // Test with same contract address (should return true)
71
146
  let result = oapp_client.is_compose_msg_sender(&origin, &message, &oapp_client.address);
72
147
  assert_eq!(result, true);
73
- }
74
-
75
- #[test]
76
- fn test_is_compose_msg_sender_different_contract() {
77
- let TestSetup { env, oapp_client, .. } = setup();
78
-
79
- let origin = Origin { src_eid: REMOTE_EID, sender: BytesN::from_array(&env, &[1; 32]), nonce: 1 };
80
- let message = Bytes::from_array(&env, &[1, 2, 3, 4]);
81
148
  let different_sender = Address::generate(&env);
82
149
 
83
150
  // Test with different sender address (should return false)
84
- let result = oapp_client.is_compose_msg_sender(&origin, &message, &different_sender);
85
- assert_eq!(result, false);
151
+ assert_eq!(oapp_client.is_compose_msg_sender(&origin, &message, &different_sender), false);
86
152
  }
87
153
 
88
154
  #[test]
89
- fn test_allow_initialize_path_with_matching_peer() {
90
- let TestSetup { env, oapp_client, .. } = setup();
91
- env.mock_all_auths();
155
+ fn test_allow_initialize_path_cases() {
156
+ let TestSetup { env, owner, oapp_client, .. } = setup();
157
+
158
+ // no peer set -> false
159
+ let origin_no_peer = Origin { src_eid: UNSET_EID, sender: BytesN::from_array(&env, &[5; 32]), nonce: 1 };
160
+ assert_eq!(oapp_client.allow_initialize_path(&origin_no_peer), false);
92
161
 
162
+ // set peer for REMOTE_EID
93
163
  let peer_bytes: BytesN<32> = BytesN::from_array(&env, &[5; 32]);
94
- oapp_client.set_peer(&REMOTE_EID, &Some(peer_bytes.clone()));
164
+ set_peer(&env, &owner, &oapp_client, REMOTE_EID, &peer_bytes);
95
165
 
96
- let origin = Origin { src_eid: REMOTE_EID, sender: peer_bytes.clone(), nonce: 1 };
166
+ // matching -> true
167
+ let origin_match = Origin { src_eid: REMOTE_EID, sender: peer_bytes.clone(), nonce: 1 };
168
+ assert_eq!(oapp_client.allow_initialize_path(&origin_match), true);
97
169
 
98
- let result = oapp_client.allow_initialize_path(&origin);
99
- assert_eq!(result, true);
170
+ // non-matching -> false
171
+ let origin_non_match = Origin { src_eid: REMOTE_EID, sender: BytesN::from_array(&env, &[6; 32]), nonce: 1 };
172
+ assert_eq!(oapp_client.allow_initialize_path(&origin_non_match), false);
100
173
  }
101
174
 
102
175
  #[test]
103
- fn test_allow_initialize_path_with_non_matching_peer() {
104
- let TestSetup { env, oapp_client, .. } = setup();
105
- env.mock_all_auths();
106
-
107
- let peer_bytes: BytesN<32> = BytesN::from_array(&env, &[5; 32]);
108
- oapp_client.set_peer(&REMOTE_EID, &Some(peer_bytes));
176
+ fn test_lz_receive_verifies_peer_and_calls_clear_value_zero() {
177
+ let TestSetup { env, owner, endpoint, oapp_client, .. } = setup();
178
+
179
+ // Configure peer
180
+ let peer: BytesN<32> = BytesN::from_array(&env, &[7; 32]);
181
+ set_peer(&env, &owner, &oapp_client, REMOTE_EID, &peer);
182
+
183
+ let executor = Address::generate(&env);
184
+ let origin = Origin { src_eid: REMOTE_EID, sender: peer, nonce: 1 };
185
+ let guid = BytesN::from_array(&env, &[2u8; 32]);
186
+ let message = Bytes::from_array(&env, &[1, 2, 3]);
187
+ let extra_data = Bytes::new(&env);
188
+ lz_receive(&env, &oapp_client, &executor, &origin, &guid, &message, &extra_data, 0, &[]);
189
+
190
+ let endpoint_client = MockEndpointClient::new(&env, &endpoint);
191
+ let (caller, cleared_origin, receiver, cleared_guid, cleared_message) = endpoint_client.last_clear();
192
+ assert_eq!(caller, oapp_client.address);
193
+ assert_eq!(cleared_origin, origin);
194
+ assert_eq!(receiver, oapp_client.address);
195
+ assert_eq!(cleared_guid, guid);
196
+ assert_eq!(cleared_message, message);
197
+ }
109
198
 
110
- let different_sender: BytesN<32> = BytesN::from_array(&env, &[6; 32]);
111
- let origin = Origin { src_eid: REMOTE_EID, sender: different_sender, nonce: 1 };
199
+ #[test]
200
+ fn test_lz_receive_transfers_native_token_when_value_positive() {
201
+ let TestSetup { env, owner, endpoint, native_token, native_token_admin_client, token_admin, oapp_client, .. } =
202
+ setup();
203
+
204
+ // Configure peer
205
+ let peer: BytesN<32> = BytesN::from_array(&env, &[9; 32]);
206
+ set_peer(&env, &owner, &oapp_client, REMOTE_EID, &peer);
207
+
208
+ let executor = Address::generate(&env);
209
+ let origin = Origin { src_eid: REMOTE_EID, sender: peer, nonce: 1 };
210
+ let guid = BytesN::from_array(&env, &[3u8; 32]);
211
+ let message = Bytes::from_array(&env, &[4, 5, 6]);
212
+ let extra_data = Bytes::new(&env);
213
+ let value: i128 = 123;
214
+
215
+ // Mint native token to executor (admin auth)
216
+ env.mock_auths(&[MockAuth {
217
+ address: &token_admin,
218
+ invoke: &MockAuthInvoke {
219
+ contract: &native_token,
220
+ fn_name: "mint",
221
+ args: (&executor, &value).into_val(&env),
222
+ sub_invokes: &[],
223
+ },
224
+ }]);
225
+ native_token_admin_client.mint(&executor, &value);
226
+
227
+ // lz_receive should transfer tokens from executor -> oapp
228
+ let transfer_invoke = MockAuthInvoke {
229
+ contract: &native_token,
230
+ fn_name: "transfer",
231
+ args: (&executor, &oapp_client.address, &value).into_val(&env),
232
+ sub_invokes: &[],
233
+ };
234
+ let sub_invokes = [transfer_invoke];
235
+ lz_receive(&env, &oapp_client, &executor, &origin, &guid, &message, &extra_data, value, &sub_invokes);
236
+
237
+ let endpoint_client = MockEndpointClient::new(&env, &endpoint);
238
+ // Asserts clear() was called (last_clear() will panic if not)
239
+ endpoint_client.last_clear();
240
+
241
+ let token_client = soroban_sdk::token::TokenClient::new(&env, &native_token);
242
+ assert_eq!(token_client.balance(&executor), 0);
243
+ assert_eq!(token_client.balance(&oapp_client.address), value);
244
+ }
112
245
 
113
- let result = oapp_client.allow_initialize_path(&origin);
114
- assert_eq!(result, false);
246
+ #[test]
247
+ fn test_lz_receive_rejects_negative_value_and_does_not_clear() {
248
+ let TestSetup { env, owner, endpoint, native_token, native_token_admin_client, token_admin, oapp_client, .. } =
249
+ setup();
250
+
251
+ // Configure peer
252
+ let peer: BytesN<32> = BytesN::from_array(&env, &[9; 32]);
253
+ set_peer(&env, &owner, &oapp_client, REMOTE_EID, &peer);
254
+
255
+ let executor = Address::generate(&env);
256
+ let origin = Origin { src_eid: REMOTE_EID, sender: peer, nonce: 1 };
257
+ let guid = BytesN::from_array(&env, &[3u8; 32]);
258
+ let message = Bytes::from_array(&env, &[4, 5, 6]);
259
+ let extra_data = Bytes::new(&env);
260
+ let value: i128 = -123;
261
+
262
+ // Fund executor with a positive balance so the only failure is the negative amount.
263
+ env.mock_auths(&[MockAuth {
264
+ address: &token_admin,
265
+ invoke: &MockAuthInvoke {
266
+ contract: &native_token,
267
+ fn_name: "mint",
268
+ args: (&executor, &(-value)).into_val(&env),
269
+ sub_invokes: &[],
270
+ },
271
+ }]);
272
+ native_token_admin_client.mint(&executor, &(-value));
273
+
274
+ // lz_receive should attempt transfer with a negative value and fail.
275
+ let transfer_invoke = MockAuthInvoke {
276
+ contract: &native_token,
277
+ fn_name: "transfer",
278
+ args: (&executor, &oapp_client.address, &value).into_val(&env),
279
+ sub_invokes: &[],
280
+ };
281
+ let sub_invokes = [transfer_invoke];
282
+ env.mock_auths(&[MockAuth {
283
+ address: &executor,
284
+ invoke: &MockAuthInvoke {
285
+ contract: &oapp_client.address,
286
+ fn_name: "lz_receive",
287
+ args: (&executor, &origin, &guid, &message, &extra_data, &value).into_val(&env),
288
+ sub_invokes: &sub_invokes,
289
+ },
290
+ }]);
291
+
292
+ let result = oapp_client.try_lz_receive(&executor, &origin, &guid, &message, &extra_data, &value);
293
+ assert_eq!(result.err().unwrap().ok().unwrap(), soroban_sdk::Error::from_contract_error(8)); //negative amount is not allowed
294
+
295
+ // No balances changed.
296
+ let token_client = soroban_sdk::token::TokenClient::new(&env, &native_token);
297
+ assert_eq!(token_client.balance(&executor), -value);
298
+ assert_eq!(token_client.balance(&oapp_client.address), 0);
299
+
300
+ // Payload should not have been cleared.
301
+ let endpoint_client = MockEndpointClient::new(&env, &endpoint);
302
+ assert!(endpoint_client.try_last_clear().is_err());
115
303
  }
116
304
 
117
305
  #[test]
118
- fn test_allow_initialize_path_with_no_peer_set() {
306
+ fn test_next_nonce_defaults_to_zero() {
119
307
  let TestSetup { env, oapp_client, .. } = setup();
308
+ let sender = BytesN::from_array(&env, &[1u8; 32]);
309
+ assert_eq!(oapp_client.next_nonce(&REMOTE_EID, &sender), 0);
310
+ }
120
311
 
121
- let origin = Origin { src_eid: UNSET_EID, sender: BytesN::from_array(&env, &[5; 32]), nonce: 1 };
122
-
123
- let result = oapp_client.allow_initialize_path(&origin);
124
- assert_eq!(result, false);
312
+ #[test]
313
+ #[should_panic(expected = "HostError: Error(Auth, InvalidAction)")]
314
+ fn test_lz_receive_requires_executor_auth() {
315
+ let TestSetup { env, owner, oapp_client, .. } = setup();
316
+
317
+ let peer: BytesN<32> = BytesN::from_array(&env, &[7; 32]);
318
+ set_peer(&env, &owner, &oapp_client, REMOTE_EID, &peer);
319
+
320
+ // Call without executor auth mocked -> should fail at executor.require_auth()
321
+ let executor = Address::generate(&env);
322
+ let origin = Origin { src_eid: REMOTE_EID, sender: peer, nonce: 1 };
323
+ let guid = BytesN::from_array(&env, &[2u8; 32]);
324
+ let message = Bytes::from_array(&env, &[1, 2, 3]);
325
+ let extra_data = Bytes::new(&env);
326
+ oapp_client.lz_receive(&executor, &origin, &guid, &message, &extra_data, &0);
125
327
  }
126
328
 
127
329
  #[test]
128
- fn test_assert_allowed_peer_wrong_sender() {
129
- let TestSetup { env, oapp_client, .. } = setup();
130
- env.mock_all_auths();
330
+ fn test_lz_receive_wrong_peer_returns_only_peer_error() {
331
+ let TestSetup { env, owner, oapp_client, .. } = setup();
131
332
 
132
- let peer_bytes: BytesN<32> = BytesN::from_array(&env, &[7; 32]);
133
- oapp_client.set_peer(&REMOTE_EID, &Some(peer_bytes));
333
+ let configured_peer: BytesN<32> = BytesN::from_array(&env, &[7; 32]);
334
+ set_peer(&env, &owner, &oapp_client, REMOTE_EID, &configured_peer);
134
335
 
336
+ let executor = Address::generate(&env);
135
337
  let wrong_sender: BytesN<32> = BytesN::from_array(&env, &[8; 32]);
136
338
  let origin = Origin { src_eid: REMOTE_EID, sender: wrong_sender, nonce: 1 };
137
-
138
- // This should panic with OnlyPeer error
139
- let result = oapp_client.try_assert_allowed_peer(&origin);
339
+ let guid = BytesN::from_array(&env, &[2u8; 32]);
340
+ let message = Bytes::from_array(&env, &[1, 2, 3]);
341
+ let extra_data = Bytes::new(&env);
342
+ let value: i128 = 0;
343
+
344
+ env.mock_auths(&[MockAuth {
345
+ address: &executor,
346
+ invoke: &MockAuthInvoke {
347
+ contract: &oapp_client.address,
348
+ fn_name: "lz_receive",
349
+ args: (&executor, &origin, &guid, &message, &extra_data, &value).into_val(&env),
350
+ sub_invokes: &[],
351
+ },
352
+ }]);
353
+ let result = oapp_client.try_lz_receive(&executor, &origin, &guid, &message, &extra_data, &value);
140
354
  assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::OnlyPeer.into());
141
355
  }
142
356
 
143
357
  #[test]
144
- fn test_assert_allowed_peer_no_peer() {
358
+ fn test_lz_receive_no_peer_returns_only_peer_error() {
145
359
  let TestSetup { env, oapp_client, .. } = setup();
146
- env.mock_all_auths();
147
360
 
148
- let origin = Origin { src_eid: UNSET_EID, sender: BytesN::from_array(&env, &[7; 32]), nonce: 1 };
149
-
150
- // This should panic with NoPeer error
151
- let result = oapp_client.try_assert_allowed_peer(&origin);
152
- assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::NoPeer.into());
361
+ let executor = Address::generate(&env);
362
+ let origin = Origin { src_eid: REMOTE_EID, sender: BytesN::from_array(&env, &[1; 32]), nonce: 1 };
363
+ let guid = BytesN::from_array(&env, &[2u8; 32]);
364
+ let message = Bytes::from_array(&env, &[1, 2, 3]);
365
+ let extra_data = Bytes::new(&env);
366
+ let value: i128 = 0;
367
+
368
+ env.mock_auths(&[MockAuth {
369
+ address: &executor,
370
+ invoke: &MockAuthInvoke {
371
+ contract: &oapp_client.address,
372
+ fn_name: "lz_receive",
373
+ args: (&executor, &origin, &guid, &message, &extra_data, &value).into_val(&env),
374
+ sub_invokes: &[],
375
+ },
376
+ }]);
377
+
378
+ // No peer configured -> should fail the peer check with OnlyPeer
379
+ let result = oapp_client.try_lz_receive(&executor, &origin, &guid, &message, &extra_data, &value);
380
+ assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::OnlyPeer.into());
153
381
  }