@layerzerolabs/protocol-stellar-v2 0.2.18 → 0.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/.turbo/turbo-build.log +275 -248
  2. package/.turbo/turbo-lint.log +52 -58
  3. package/.turbo/turbo-test.log +1224 -1358
  4. package/Cargo.lock +8 -5
  5. package/Cargo.toml +1 -1
  6. package/contracts/ERROR_SPEC.md +1 -1
  7. package/contracts/message-libs/uln-302/src/send_uln.rs +1 -1
  8. package/contracts/oapps/oapp/src/oapp_receiver.rs +1 -1
  9. package/contracts/oapps/oft/Cargo.toml +10 -7
  10. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_oft_fee.rs +3 -4
  11. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_pausable.rs +2 -3
  12. package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_rate_limiter.rs +1 -1
  13. package/contracts/oapps/oft/integration-tests/mod.rs +1 -1
  14. package/contracts/oapps/oft/integration-tests/setup.rs +28 -127
  15. package/contracts/oapps/oft/integration-tests/utils.rs +254 -21
  16. package/contracts/oapps/oft/src/extensions/oft_fee.rs +5 -6
  17. package/contracts/oapps/oft/src/lib.rs +10 -14
  18. package/contracts/oapps/oft/src/oft.rs +151 -189
  19. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +9 -11
  20. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +32 -12
  21. package/contracts/oapps/oft/src/oft_types/mod.rs +13 -0
  22. package/contracts/oapps/{oft-std → oft-core}/Cargo.toml +6 -4
  23. package/contracts/oapps/{oft-std → oft-core}/integration-tests/mod.rs +1 -1
  24. package/contracts/oapps/{oft-std → oft-core}/integration-tests/setup.rs +126 -29
  25. package/contracts/oapps/{oft → oft-core}/integration-tests/test_with_sml.rs +3 -3
  26. package/contracts/oapps/oft-core/integration-tests/utils.rs +201 -0
  27. package/contracts/oapps/oft-core/src/lib.rs +18 -0
  28. package/contracts/oapps/oft-core/src/oft_core.rs +439 -0
  29. package/contracts/oapps/{oft → oft-core}/src/tests/mod.rs +0 -2
  30. package/contracts/oapps/{oft → oft-core}/src/tests/test_lz_receive.rs +7 -7
  31. package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_msg_codec.rs +4 -4
  32. package/contracts/oapps/{oft → oft-core}/src/tests/test_resolve_address.rs +3 -3
  33. package/contracts/oapps/{oft → oft-core}/src/tests/test_utils.rs +44 -25
  34. package/contracts/oapps/{oft → oft-core}/src/utils.rs +1 -1
  35. package/contracts/utils/src/errors.rs +5 -1
  36. package/contracts/utils/src/ownable.rs +125 -3
  37. package/contracts/utils/src/tests/option_ext.rs +1 -1
  38. package/contracts/utils/src/tests/ownable.rs +445 -7
  39. package/contracts/utils/src/tests/ttl_configurable.rs +2 -2
  40. package/package.json +4 -5
  41. package/sdk/.turbo/turbo-test.log +216 -206
  42. package/sdk/dist/generated/bml.d.ts +30 -0
  43. package/sdk/dist/generated/bml.js +28 -5
  44. package/sdk/dist/generated/counter.d.ts +122 -2
  45. package/sdk/dist/generated/counter.js +36 -7
  46. package/sdk/dist/generated/dvn.d.ts +30 -0
  47. package/sdk/dist/generated/dvn.js +28 -5
  48. package/sdk/dist/generated/dvn_fee_lib.d.ts +122 -2
  49. package/sdk/dist/generated/dvn_fee_lib.js +36 -7
  50. package/sdk/dist/generated/endpoint.d.ts +122 -2
  51. package/sdk/dist/generated/endpoint.js +36 -7
  52. package/sdk/dist/generated/executor.d.ts +122 -2
  53. package/sdk/dist/generated/executor.js +36 -7
  54. package/sdk/dist/generated/executor_fee_lib.d.ts +122 -2
  55. package/sdk/dist/generated/executor_fee_lib.js +36 -7
  56. package/sdk/dist/generated/executor_helper.d.ts +30 -0
  57. package/sdk/dist/generated/executor_helper.js +28 -5
  58. package/sdk/dist/generated/oft.d.ts +1842 -0
  59. package/sdk/dist/generated/oft.js +345 -0
  60. package/sdk/dist/generated/price_feed.d.ts +122 -2
  61. package/sdk/dist/generated/price_feed.js +36 -7
  62. package/sdk/dist/generated/sml.d.ts +122 -2
  63. package/sdk/dist/generated/sml.js +36 -7
  64. package/sdk/dist/generated/treasury.d.ts +122 -2
  65. package/sdk/dist/generated/treasury.js +36 -7
  66. package/sdk/dist/generated/uln302.d.ts +122 -2
  67. package/sdk/dist/generated/uln302.js +36 -7
  68. package/sdk/dist/generated/upgrader.d.ts +15 -0
  69. package/sdk/dist/generated/upgrader.js +18 -0
  70. package/sdk/dist/index.d.ts +1 -2
  71. package/sdk/dist/index.js +1 -3
  72. package/sdk/package.json +3 -2
  73. package/sdk/src/index.ts +1 -4
  74. package/sdk/test/oft-sml.test.ts +16 -16
  75. package/sdk/turbo.json +8 -0
  76. package/tools/ts-bindings-gen/Cargo.toml +2 -0
  77. package/tools/ts-bindings-gen/src/main.rs +51 -4
  78. package/turbo.json +0 -2
  79. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +0 -23
  80. package/contracts/oapps/oft/src/interfaces/mod.rs +0 -3
  81. package/contracts/oapps/oft/src/oft_impl.rs +0 -201
  82. package/contracts/oapps/oft/src/tests/extensions/mod.rs +0 -11
  83. package/contracts/oapps/oft/src/tests/extensions/setup.rs +0 -917
  84. package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +0 -751
  85. package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +0 -434
  86. package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +0 -1080
  87. package/contracts/oapps/oft-std/integration-tests/utils.rs +0 -427
  88. package/contracts/oapps/oft-std/src/lib.rs +0 -16
  89. package/contracts/oapps/oft-std/src/oft.rs +0 -174
  90. package/sdk/dist/generated/oft_std.d.ts +0 -1722
  91. package/sdk/dist/generated/oft_std.js +0 -316
  92. package/sdk/dist/wasm/blocked-message-lib.d.ts +0 -1
  93. package/sdk/dist/wasm/blocked-message-lib.js +0 -2
  94. package/sdk/dist/wasm/counter.d.ts +0 -1
  95. package/sdk/dist/wasm/counter.js +0 -2
  96. package/sdk/dist/wasm/dvn-fee-lib.d.ts +0 -1
  97. package/sdk/dist/wasm/dvn-fee-lib.js +0 -2
  98. package/sdk/dist/wasm/dvn.d.ts +0 -1
  99. package/sdk/dist/wasm/dvn.js +0 -2
  100. package/sdk/dist/wasm/endpoint-v2.d.ts +0 -1
  101. package/sdk/dist/wasm/endpoint-v2.js +0 -2
  102. package/sdk/dist/wasm/executor-fee-lib.d.ts +0 -1
  103. package/sdk/dist/wasm/executor-fee-lib.js +0 -2
  104. package/sdk/dist/wasm/executor-helper.d.ts +0 -1
  105. package/sdk/dist/wasm/executor-helper.js +0 -2
  106. package/sdk/dist/wasm/executor.d.ts +0 -1
  107. package/sdk/dist/wasm/executor.js +0 -2
  108. package/sdk/dist/wasm/layerzero-views.d.ts +0 -1
  109. package/sdk/dist/wasm/layerzero-views.js +0 -2
  110. package/sdk/dist/wasm/oft-std.d.ts +0 -1
  111. package/sdk/dist/wasm/oft-std.js +0 -2
  112. package/sdk/dist/wasm/price-feed.d.ts +0 -1
  113. package/sdk/dist/wasm/price-feed.js +0 -2
  114. package/sdk/dist/wasm/simple-message-lib.d.ts +0 -1
  115. package/sdk/dist/wasm/simple-message-lib.js +0 -2
  116. package/sdk/dist/wasm/treasury.d.ts +0 -1
  117. package/sdk/dist/wasm/treasury.js +0 -2
  118. package/sdk/dist/wasm/uln302.d.ts +0 -1
  119. package/sdk/dist/wasm/uln302.js +0 -2
  120. package/sdk/dist/wasm/upgrader.d.ts +0 -1
  121. package/sdk/dist/wasm/upgrader.js +0 -2
  122. package/sdk/dist/wasm.d.ts +0 -15
  123. package/sdk/dist/wasm.js +0 -15
  124. /package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/mod.rs +0 -0
  125. /package/contracts/oapps/{oft → oft-core}/src/codec/mod.rs +0 -0
  126. /package/contracts/oapps/{oft → oft-core}/src/codec/oft_compose_msg_codec.rs +0 -0
  127. /package/contracts/oapps/{oft → oft-core}/src/codec/oft_msg_codec.rs +0 -0
  128. /package/contracts/oapps/{oft → oft-core}/src/errors.rs +0 -0
  129. /package/contracts/oapps/{oft → oft-core}/src/events.rs +0 -0
  130. /package/contracts/oapps/{oft → oft-core}/src/storage.rs +0 -0
  131. /package/contracts/oapps/{oft → oft-core}/src/tests/test_decimals.rs +0 -0
  132. /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_compose_msg_codec.rs +0 -0
  133. /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_version.rs +0 -0
  134. /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_oft.rs +0 -0
  135. /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_send.rs +0 -0
  136. /package/contracts/oapps/{oft → oft-core}/src/tests/test_send.rs +0 -0
  137. /package/contracts/oapps/{oft → oft-core}/src/tests/test_token.rs +0 -0
  138. /package/contracts/oapps/{oft → oft-core}/src/types.rs +0 -0
@@ -2,7 +2,10 @@ use crate::{
2
2
  auth::Auth,
3
3
  errors::OwnableError,
4
4
  option_ext::OptionExt,
5
- ownable::{self, Ownable, OwnableInitializer, OwnableStorage, OwnershipRenounced, OwnershipTransferred},
5
+ ownable::{
6
+ self, Ownable, OwnableInitializer, OwnableStorage, OwnershipRenounced, OwnershipTransferred,
7
+ OwnershipTransferring,
8
+ },
6
9
  testing_utils::assert_event,
7
10
  };
8
11
  use soroban_sdk::{
@@ -87,7 +90,7 @@ fn auth_non_owner_cannot_call() {
87
90
  }
88
91
 
89
92
  #[test]
90
- #[should_panic(expected = "Error(Contract, #1031)")] // OwnerNotSet
93
+ #[should_panic(expected = "Error(Contract, #1034)")] // OwnerNotSet
91
94
  fn auth_require_owner_when_no_owner_set() {
92
95
  let env = Env::default();
93
96
  let owner = Address::generate(&env);
@@ -109,7 +112,7 @@ fn auth_require_owner_when_no_owner_set() {
109
112
  }
110
113
 
111
114
  // ============================================
112
- // transfer: Transfer ownership tests
115
+ // transfer: Single-step transfer ownership tests
113
116
  // ============================================
114
117
 
115
118
  #[test]
@@ -165,7 +168,7 @@ fn transfer_ownership_to_same_owner() {
165
168
  }
166
169
 
167
170
  #[test]
168
- #[should_panic(expected = "Error(Contract, #1031)")] // OwnerNotSet
171
+ #[should_panic(expected = "Error(Contract, #1034)")] // OwnerNotSet
169
172
  fn transfer_after_renounce_fails() {
170
173
  let env = Env::default();
171
174
  let owner = Address::generate(&env);
@@ -199,6 +202,343 @@ fn transfer_after_renounce_fails() {
199
202
  client.transfer_ownership(&new_owner);
200
203
  }
201
204
 
205
+ #[test]
206
+ #[should_panic(expected = "Error(Contract, #1035)")] // TransferInProgress
207
+ fn transfer_ownership_blocked_during_2step() {
208
+ let env = Env::default();
209
+ let owner = Address::generate(&env);
210
+ let new_owner = Address::generate(&env);
211
+ let another_owner = Address::generate(&env);
212
+
213
+ let contract = env.register(Contract, (&owner,));
214
+ let client = ContractClient::new(&env, &contract);
215
+
216
+ let ttl = 1000u32;
217
+
218
+ // Initiate 2-step transfer
219
+ env.mock_auths(&[MockAuth {
220
+ address: &owner,
221
+ invoke: &MockAuthInvoke {
222
+ contract: &contract,
223
+ args: (&new_owner, ttl).into_val(&env),
224
+ fn_name: "propose_ownership_transfer",
225
+ sub_invokes: &[],
226
+ },
227
+ }]);
228
+ client.propose_ownership_transfer(&new_owner, &ttl);
229
+
230
+ // Try single-step transfer - should fail
231
+ env.mock_auths(&[MockAuth {
232
+ address: &owner,
233
+ invoke: &MockAuthInvoke {
234
+ contract: &contract,
235
+ args: (&another_owner,).into_val(&env),
236
+ fn_name: "transfer_ownership",
237
+ sub_invokes: &[],
238
+ },
239
+ }]);
240
+ client.transfer_ownership(&another_owner);
241
+ }
242
+
243
+ // ============================================
244
+ // transfer_2step: Two-step transfer ownership tests
245
+ // ============================================
246
+
247
+ #[test]
248
+ fn propose_ownership_transfer_initiate_and_accept() {
249
+ let env = Env::default();
250
+ let owner = Address::generate(&env);
251
+ let new_owner = Address::generate(&env);
252
+
253
+ let contract = env.register(Contract, (&owner,));
254
+ let client = ContractClient::new(&env, &contract);
255
+
256
+ let ttl = 1000u32;
257
+
258
+ assert_eq!(client.owner(), Some(owner.clone()));
259
+ assert_eq!(client.pending_owner(), None);
260
+
261
+ // Step 1: Initiate transfer
262
+ env.mock_auths(&[MockAuth {
263
+ address: &owner,
264
+ invoke: &MockAuthInvoke {
265
+ contract: &contract,
266
+ args: (&new_owner, ttl).into_val(&env),
267
+ fn_name: "propose_ownership_transfer",
268
+ sub_invokes: &[],
269
+ },
270
+ }]);
271
+ client.propose_ownership_transfer(&new_owner, &ttl);
272
+
273
+ assert_event(
274
+ &env,
275
+ &contract,
276
+ OwnershipTransferring { old_owner: owner.clone(), new_owner: new_owner.clone(), ttl },
277
+ );
278
+ assert_eq!(client.owner(), Some(owner.clone())); // Still old owner
279
+ assert_eq!(client.pending_owner(), Some(new_owner.clone()));
280
+
281
+ // Step 2: Accept transfer
282
+ env.mock_auths(&[MockAuth {
283
+ address: &new_owner,
284
+ invoke: &MockAuthInvoke {
285
+ contract: &contract,
286
+ args: ().into_val(&env),
287
+ fn_name: "accept_ownership",
288
+ sub_invokes: &[],
289
+ },
290
+ }]);
291
+ client.accept_ownership();
292
+
293
+ assert_event(&env, &contract, OwnershipTransferred { old_owner: owner, new_owner: new_owner.clone() });
294
+ assert_eq!(client.owner(), Some(new_owner)); // Now new owner
295
+ assert_eq!(client.pending_owner(), None);
296
+ }
297
+
298
+ #[test]
299
+ fn propose_ownership_transfer_cancel() {
300
+ let env = Env::default();
301
+ let owner = Address::generate(&env);
302
+ let new_owner = Address::generate(&env);
303
+
304
+ let contract = env.register(Contract, (&owner,));
305
+ let client = ContractClient::new(&env, &contract);
306
+
307
+ let ttl = 1000u32;
308
+
309
+ // Initiate transfer
310
+ env.mock_auths(&[MockAuth {
311
+ address: &owner,
312
+ invoke: &MockAuthInvoke {
313
+ contract: &contract,
314
+ args: (&new_owner, ttl).into_val(&env),
315
+ fn_name: "propose_ownership_transfer",
316
+ sub_invokes: &[],
317
+ },
318
+ }]);
319
+ client.propose_ownership_transfer(&new_owner, &ttl);
320
+
321
+ assert_eq!(client.pending_owner(), Some(new_owner.clone()));
322
+
323
+ // Cancel transfer (ttl = 0)
324
+ env.mock_auths(&[MockAuth {
325
+ address: &owner,
326
+ invoke: &MockAuthInvoke {
327
+ contract: &contract,
328
+ args: (&new_owner, 0u32).into_val(&env),
329
+ fn_name: "propose_ownership_transfer",
330
+ sub_invokes: &[],
331
+ },
332
+ }]);
333
+ client.propose_ownership_transfer(&new_owner, &0u32);
334
+
335
+ // No event emitted on cancel (matching OpenZeppelin behavior)
336
+ assert_eq!(client.owner(), Some(owner)); // Still old owner
337
+ assert_eq!(client.pending_owner(), None);
338
+ }
339
+
340
+ #[test]
341
+ #[should_panic(expected = "Error(Contract, #1032)")] // NoPendingTransfer
342
+ fn propose_ownership_transfer_cancel_no_pending_fails() {
343
+ let env = Env::default();
344
+ let owner = Address::generate(&env);
345
+ let new_owner = Address::generate(&env);
346
+
347
+ let contract = env.register(Contract, (&owner,));
348
+ let client = ContractClient::new(&env, &contract);
349
+
350
+ // Try to cancel when no transfer is pending
351
+ env.mock_auths(&[MockAuth {
352
+ address: &owner,
353
+ invoke: &MockAuthInvoke {
354
+ contract: &contract,
355
+ args: (&new_owner, 0u32).into_val(&env),
356
+ fn_name: "propose_ownership_transfer",
357
+ sub_invokes: &[],
358
+ },
359
+ }]);
360
+ client.propose_ownership_transfer(&new_owner, &0u32);
361
+ }
362
+
363
+ #[test]
364
+ #[should_panic(expected = "Error(Contract, #1030)")] // InvalidPendingOwner
365
+ fn propose_ownership_transfer_cancel_wrong_address_fails() {
366
+ let env = Env::default();
367
+ let owner = Address::generate(&env);
368
+ let new_owner = Address::generate(&env);
369
+ let wrong_owner = Address::generate(&env);
370
+
371
+ let contract = env.register(Contract, (&owner,));
372
+ let client = ContractClient::new(&env, &contract);
373
+
374
+ let ttl = 1000u32;
375
+
376
+ // Initiate transfer
377
+ env.mock_auths(&[MockAuth {
378
+ address: &owner,
379
+ invoke: &MockAuthInvoke {
380
+ contract: &contract,
381
+ args: (&new_owner, ttl).into_val(&env),
382
+ fn_name: "propose_ownership_transfer",
383
+ sub_invokes: &[],
384
+ },
385
+ }]);
386
+ client.propose_ownership_transfer(&new_owner, &ttl);
387
+
388
+ // Try to cancel with wrong address
389
+ env.mock_auths(&[MockAuth {
390
+ address: &owner,
391
+ invoke: &MockAuthInvoke {
392
+ contract: &contract,
393
+ args: (&wrong_owner, 0u32).into_val(&env),
394
+ fn_name: "propose_ownership_transfer",
395
+ sub_invokes: &[],
396
+ },
397
+ }]);
398
+ client.propose_ownership_transfer(&wrong_owner, &0u32);
399
+ }
400
+
401
+ #[test]
402
+ #[should_panic(expected = "Error(Contract, #1031)")] // InvalidTtl
403
+ fn propose_ownership_transfer_invalid_ttl_exceeds_max_fails() {
404
+ let env = Env::default();
405
+ let owner = Address::generate(&env);
406
+ let new_owner = Address::generate(&env);
407
+
408
+ let contract = env.register(Contract, (&owner,));
409
+ let client = ContractClient::new(&env, &contract);
410
+
411
+ // TTL that would exceed max_live_until_ledger
412
+ let ttl = u32::MAX;
413
+
414
+ env.mock_auths(&[MockAuth {
415
+ address: &owner,
416
+ invoke: &MockAuthInvoke {
417
+ contract: &contract,
418
+ args: (&new_owner, ttl).into_val(&env),
419
+ fn_name: "propose_ownership_transfer",
420
+ sub_invokes: &[],
421
+ },
422
+ }]);
423
+ client.propose_ownership_transfer(&new_owner, &ttl);
424
+ }
425
+
426
+ #[test]
427
+ #[should_panic(expected = "Error(Contract, #1032)")] // NoPendingTransfer
428
+ fn accept_ownership_no_pending_fails() {
429
+ let env = Env::default();
430
+ let owner = Address::generate(&env);
431
+ let new_owner = Address::generate(&env);
432
+
433
+ let contract = env.register(Contract, (&owner,));
434
+ let client = ContractClient::new(&env, &contract);
435
+
436
+ // Try to accept when no transfer is pending
437
+ env.mock_auths(&[MockAuth {
438
+ address: &new_owner,
439
+ invoke: &MockAuthInvoke {
440
+ contract: &contract,
441
+ args: ().into_val(&env),
442
+ fn_name: "accept_ownership",
443
+ sub_invokes: &[],
444
+ },
445
+ }]);
446
+ client.accept_ownership();
447
+ }
448
+
449
+ #[test]
450
+ #[should_panic(expected = "Error(Auth, InvalidAction)")]
451
+ fn accept_ownership_wrong_address_fails() {
452
+ let env = Env::default();
453
+ let owner = Address::generate(&env);
454
+ let new_owner = Address::generate(&env);
455
+ let wrong_owner = Address::generate(&env);
456
+
457
+ let contract = env.register(Contract, (&owner,));
458
+ let client = ContractClient::new(&env, &contract);
459
+
460
+ let ttl = 1000u32;
461
+
462
+ // Initiate transfer
463
+ env.mock_auths(&[MockAuth {
464
+ address: &owner,
465
+ invoke: &MockAuthInvoke {
466
+ contract: &contract,
467
+ args: (&new_owner, ttl).into_val(&env),
468
+ fn_name: "propose_ownership_transfer",
469
+ sub_invokes: &[],
470
+ },
471
+ }]);
472
+ client.propose_ownership_transfer(&new_owner, &ttl);
473
+
474
+ // Try to accept with wrong address
475
+ env.mock_auths(&[MockAuth {
476
+ address: &wrong_owner,
477
+ invoke: &MockAuthInvoke {
478
+ contract: &contract,
479
+ args: ().into_val(&env),
480
+ fn_name: "accept_ownership",
481
+ sub_invokes: &[],
482
+ },
483
+ }]);
484
+ client.accept_ownership();
485
+ }
486
+
487
+ #[test]
488
+ fn propose_ownership_transfer_override_pending() {
489
+ let env = Env::default();
490
+ let owner = Address::generate(&env);
491
+ let new_owner1 = Address::generate(&env);
492
+ let new_owner2 = Address::generate(&env);
493
+
494
+ let contract = env.register(Contract, (&owner,));
495
+ let client = ContractClient::new(&env, &contract);
496
+
497
+ let ttl = 1000u32;
498
+
499
+ // Initiate first transfer
500
+ env.mock_auths(&[MockAuth {
501
+ address: &owner,
502
+ invoke: &MockAuthInvoke {
503
+ contract: &contract,
504
+ args: (&new_owner1, ttl).into_val(&env),
505
+ fn_name: "propose_ownership_transfer",
506
+ sub_invokes: &[],
507
+ },
508
+ }]);
509
+ client.propose_ownership_transfer(&new_owner1, &ttl);
510
+
511
+ assert_eq!(client.pending_owner(), Some(new_owner1.clone()));
512
+
513
+ // Override with second transfer (allowed - replaces pending)
514
+ env.mock_auths(&[MockAuth {
515
+ address: &owner,
516
+ invoke: &MockAuthInvoke {
517
+ contract: &contract,
518
+ args: (&new_owner2, ttl).into_val(&env),
519
+ fn_name: "propose_ownership_transfer",
520
+ sub_invokes: &[],
521
+ },
522
+ }]);
523
+ client.propose_ownership_transfer(&new_owner2, &ttl);
524
+
525
+ assert_eq!(client.pending_owner(), Some(new_owner2.clone()));
526
+
527
+ // new_owner2 can accept
528
+ env.mock_auths(&[MockAuth {
529
+ address: &new_owner2,
530
+ invoke: &MockAuthInvoke {
531
+ contract: &contract,
532
+ args: ().into_val(&env),
533
+ fn_name: "accept_ownership",
534
+ sub_invokes: &[],
535
+ },
536
+ }]);
537
+ client.accept_ownership();
538
+
539
+ assert_eq!(client.owner(), Some(new_owner2));
540
+ }
541
+
202
542
  // ============================================
203
543
  // renounce: Renounce ownership tests
204
544
  // ============================================
@@ -229,7 +569,7 @@ fn renounce_ownership_with_event() {
229
569
  }
230
570
 
231
571
  #[test]
232
- #[should_panic(expected = "Error(Contract, #1031)")] // OwnerNotSet
572
+ #[should_panic(expected = "Error(Contract, #1034)")] // OwnerNotSet
233
573
  fn renounce_after_renounce_fails() {
234
574
  let env = Env::default();
235
575
  let owner = Address::generate(&env);
@@ -262,6 +602,43 @@ fn renounce_after_renounce_fails() {
262
602
  client.renounce_ownership();
263
603
  }
264
604
 
605
+ #[test]
606
+ #[should_panic(expected = "Error(Contract, #1035)")] // TransferInProgress
607
+ fn renounce_blocked_during_2step_transfer() {
608
+ let env = Env::default();
609
+ let owner = Address::generate(&env);
610
+ let new_owner = Address::generate(&env);
611
+
612
+ let contract = env.register(Contract, (&owner,));
613
+ let client = ContractClient::new(&env, &contract);
614
+
615
+ let ttl = 1000u32;
616
+
617
+ // Initiate 2-step transfer
618
+ env.mock_auths(&[MockAuth {
619
+ address: &owner,
620
+ invoke: &MockAuthInvoke {
621
+ contract: &contract,
622
+ args: (&new_owner, ttl).into_val(&env),
623
+ fn_name: "propose_ownership_transfer",
624
+ sub_invokes: &[],
625
+ },
626
+ }]);
627
+ client.propose_ownership_transfer(&new_owner, &ttl);
628
+
629
+ // Try to renounce - should fail
630
+ env.mock_auths(&[MockAuth {
631
+ address: &owner,
632
+ invoke: &MockAuthInvoke {
633
+ contract: &contract,
634
+ args: ().into_val(&env),
635
+ fn_name: "renounce_ownership",
636
+ sub_invokes: &[],
637
+ },
638
+ }]);
639
+ client.renounce_ownership();
640
+ }
641
+
265
642
  // ============================================
266
643
  // chain: Ownership chain tests
267
644
  // ============================================
@@ -303,12 +680,73 @@ fn chain_new_owner_can_transfer() {
303
680
  assert_eq!(client.owner(), Some(third_owner));
304
681
  }
305
682
 
683
+ #[test]
684
+ fn chain_new_owner_can_transfer_2step() {
685
+ let env = Env::default();
686
+ let owner = Address::generate(&env);
687
+ let new_owner = Address::generate(&env);
688
+ let third_owner = Address::generate(&env);
689
+
690
+ let contract = env.register(Contract, (&owner,));
691
+ let client = ContractClient::new(&env, &contract);
692
+
693
+ let ttl = 1000u32;
694
+
695
+ // 2-step transfer to new_owner
696
+ env.mock_auths(&[MockAuth {
697
+ address: &owner,
698
+ invoke: &MockAuthInvoke {
699
+ contract: &contract,
700
+ args: (&new_owner, ttl).into_val(&env),
701
+ fn_name: "propose_ownership_transfer",
702
+ sub_invokes: &[],
703
+ },
704
+ }]);
705
+ client.propose_ownership_transfer(&new_owner, &ttl);
706
+
707
+ env.mock_auths(&[MockAuth {
708
+ address: &new_owner,
709
+ invoke: &MockAuthInvoke {
710
+ contract: &contract,
711
+ args: ().into_val(&env),
712
+ fn_name: "accept_ownership",
713
+ sub_invokes: &[],
714
+ },
715
+ }]);
716
+ client.accept_ownership();
717
+
718
+ // new_owner can now do another 2-step transfer
719
+ env.mock_auths(&[MockAuth {
720
+ address: &new_owner,
721
+ invoke: &MockAuthInvoke {
722
+ contract: &contract,
723
+ args: (&third_owner, ttl).into_val(&env),
724
+ fn_name: "propose_ownership_transfer",
725
+ sub_invokes: &[],
726
+ },
727
+ }]);
728
+ client.propose_ownership_transfer(&third_owner, &ttl);
729
+
730
+ env.mock_auths(&[MockAuth {
731
+ address: &third_owner,
732
+ invoke: &MockAuthInvoke {
733
+ contract: &contract,
734
+ args: ().into_val(&env),
735
+ fn_name: "accept_ownership",
736
+ sub_invokes: &[],
737
+ },
738
+ }]);
739
+ client.accept_ownership();
740
+
741
+ assert_eq!(client.owner(), Some(third_owner));
742
+ }
743
+
306
744
  // ============================================
307
745
  // init: DefaultOwnable::init_owner tests
308
746
  // ============================================
309
747
 
310
748
  #[test]
311
- #[should_panic(expected = "Error(Contract, #1030)")] // OwnerAlreadySet
749
+ #[should_panic(expected = "Error(Contract, #1033)")] // OwnerAlreadySet
312
750
  fn reinit_owner_fails() {
313
751
  let env = Env::default();
314
752
  let owner = Address::generate(&env);
@@ -345,7 +783,7 @@ fn enforce_owner_auth_returns_owner() {
345
783
  }
346
784
 
347
785
  #[test]
348
- #[should_panic(expected = "Error(Contract, #1031)")] // OwnerNotSet
786
+ #[should_panic(expected = "Error(Contract, #1034)")] // OwnerNotSet
349
787
  fn enforce_owner_auth_no_owner_set_fails() {
350
788
  let env = Env::default();
351
789
  let owner = Address::generate(&env);
@@ -423,7 +423,7 @@ fn test_default_ttl_configurable_freeze_wrong_signer_fails() {
423
423
  }
424
424
 
425
425
  #[test]
426
- #[should_panic(expected = "Error(Contract, #1031)")] // OwnerNotSet
426
+ #[should_panic(expected = "Error(Contract, #1034)")] // OwnerNotSet
427
427
  fn test_default_ttl_configurable_freeze_when_owner_not_set() {
428
428
  let env = Env::default();
429
429
  let contract_id = env.register(TtlTestContract, ());
@@ -529,7 +529,7 @@ fn test_default_ttl_configurable_set_wrong_signer_fails() {
529
529
  }
530
530
 
531
531
  #[test]
532
- #[should_panic(expected = "Error(Contract, #1031)")] // OwnerNotSet
532
+ #[should_panic(expected = "Error(Contract, #1034)")] // OwnerNotSet
533
533
  fn test_default_ttl_configurable_set_when_owner_not_set() {
534
534
  let env = Env::default();
535
535
  let contract_id = env.register(TtlTestContract, ());
package/package.json CHANGED
@@ -1,24 +1,23 @@
1
1
  {
2
2
  "name": "@layerzerolabs/protocol-stellar-v2",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "private": false,
5
5
  "devDependencies": {
6
6
  "@types/node": "^22.18.6",
7
7
  "tsx": "^4.19.3",
8
8
  "typescript": "^5.8.2",
9
- "@layerzerolabs/common-node-utils": "0.2.18",
10
- "@layerzerolabs/vm-tooling-stellar": "0.2.18"
9
+ "@layerzerolabs/common-node-utils": "0.2.19",
10
+ "@layerzerolabs/vm-tooling-stellar": "0.2.19"
11
11
  },
12
12
  "publishConfig": {
13
13
  "access": "restricted",
14
14
  "registry": "https://registry.npmjs.org/"
15
15
  },
16
16
  "scripts": {
17
- "build": "pnpm build:contracts:sandbox && pnpm generate:sdk && pnpm build:wasm",
17
+ "build": "pnpm build:contracts:sandbox && pnpm generate:sdk",
18
18
  "build:contracts:mainnet": "pnpm exec lz-tool stellar contract build --features mainnet",
19
19
  "build:contracts:sandbox": "pnpm exec lz-tool stellar contract build --features sandbox",
20
20
  "build:contracts:testnet": "pnpm exec lz-tool stellar contract build --features testnet",
21
- "build:wasm": "lz-tool extra stellar build-typescript-sdk target sdk/src",
22
21
  "format": "pnpm exec lz-tool --script \"cargo fmt\" stellar",
23
22
  "generate:sdk": "pnpm exec lz-tool --script \"cargo run -p ts-bindings-gen\" stellar",
24
23
  "lint": "pnpm exec lz-tool --script \"cargo clippy -- -D warnings\" stellar",