@layerzerolabs/protocol-stellar-v2 0.2.10 → 0.2.12

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 (129) hide show
  1. package/.turbo/turbo-build.log +273 -219
  2. package/.turbo/turbo-lint.log +79 -107
  3. package/.turbo/turbo-test.log +1016 -840
  4. package/Cargo.lock +14 -6
  5. package/contracts/common-macros/src/contract_impl.rs +6 -3
  6. package/contracts/common-macros/src/error.rs +9 -17
  7. package/contracts/common-macros/src/lib.rs +4 -37
  8. package/contracts/common-macros/src/ownable.rs +9 -5
  9. package/contracts/common-macros/src/tests/contract_impl.rs +178 -86
  10. package/contracts/common-macros/src/tests/error.rs +168 -0
  11. package/contracts/common-macros/src/tests/mod.rs +2 -4
  12. package/contracts/common-macros/src/tests/ownable.rs +37 -60
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +16 -6
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__error__snapshot_generated_contract_error_code.snap +20 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +3 -1
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +12 -2
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +5 -1
  18. package/contracts/common-macros/src/tests/utils.rs +267 -0
  19. package/contracts/common-macros/src/ttl_configurable.rs +15 -12
  20. package/contracts/common-macros/src/utils.rs +35 -6
  21. package/contracts/endpoint-v2/src/endpoint_v2.rs +4 -4
  22. package/contracts/endpoint-v2/src/events.rs +40 -22
  23. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -2
  24. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +2 -2
  25. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
  26. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
  27. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +2 -2
  28. package/contracts/endpoint-v2/src/message_lib_manager.rs +3 -3
  29. package/contracts/endpoint-v2/src/messaging_channel.rs +1 -1
  30. package/contracts/endpoint-v2/src/messaging_composer.rs +1 -1
  31. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +4 -8
  32. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +3 -7
  33. package/contracts/message-libs/{block-message-lib → blocked-message-lib}/Cargo.toml +1 -1
  34. package/contracts/message-libs/treasury/src/events.rs +9 -6
  35. package/contracts/message-libs/uln-302/src/events.rs +19 -11
  36. package/contracts/message-libs/uln-302/src/interfaces/receive_uln.rs +2 -2
  37. package/contracts/message-libs/uln-302/src/interfaces/send_uln.rs +2 -2
  38. package/contracts/message-libs/uln-302/src/receive_uln.rs +2 -2
  39. package/contracts/message-libs/uln-302/src/send_uln.rs +3 -3
  40. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +5 -5
  41. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +5 -5
  42. package/contracts/message-libs/uln-302/src/tests/setup.rs +3 -3
  43. package/contracts/message-libs/uln-302/src/types.rs +24 -24
  44. package/contracts/message-libs/uln-302/src/uln302.rs +2 -2
  45. package/contracts/oapp-macros/src/oapp_core.rs +1 -1
  46. package/contracts/oapps/counter/integration_tests/utils.rs +1 -1
  47. package/contracts/oapps/oapp/src/oapp_core.rs +4 -3
  48. package/contracts/oapps/oapp/src/oapp_options_type3.rs +4 -3
  49. package/contracts/oapps/oft/integration-tests/setup.rs +4 -3
  50. package/contracts/oapps/oft/integration-tests/utils.rs +1 -1
  51. package/contracts/oapps/oft/src/default_oft_impl.rs +146 -0
  52. package/contracts/oapps/oft/src/events.rs +5 -4
  53. package/contracts/oapps/oft/src/extensions/mod.rs +3 -0
  54. package/contracts/oapps/oft/src/extensions/oft_fee.rs +168 -0
  55. package/contracts/oapps/oft/src/extensions/pausable.rs +50 -0
  56. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +200 -0
  57. package/contracts/oapps/oft/src/lib.rs +2 -3
  58. package/contracts/oapps/oft/src/oft.rs +16 -85
  59. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +1 -1
  60. package/contracts/oapps/oft/src/tests/extensions/mod.rs +11 -0
  61. package/contracts/oapps/oft/src/tests/extensions/setup.rs +888 -0
  62. package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +749 -0
  63. package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +432 -0
  64. package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +1078 -0
  65. package/contracts/oapps/oft/src/tests/mod.rs +2 -0
  66. package/contracts/oapps/oft/src/tests/test_utils.rs +24 -6
  67. package/contracts/oapps/{oft-mint-burn → oft-std}/Cargo.toml +1 -8
  68. package/contracts/oapps/oft-std/src/lib.rs +5 -0
  69. package/contracts/oapps/oft-std/src/oft.rs +59 -0
  70. package/contracts/utils/src/ownable.rs +8 -6
  71. package/contracts/utils/src/tests/ownable.rs +0 -63
  72. package/contracts/utils/src/tests/testing_utils.rs +7 -5
  73. package/contracts/utils/src/ttl.rs +21 -2
  74. package/contracts/workers/dvn/src/auth.rs +108 -30
  75. package/contracts/workers/dvn/src/dvn.rs +103 -33
  76. package/contracts/workers/dvn/src/errors.rs +10 -13
  77. package/contracts/workers/dvn/src/events.rs +7 -5
  78. package/contracts/workers/dvn/src/interfaces/dvn.rs +76 -3
  79. package/contracts/workers/dvn/src/interfaces/multisig.rs +41 -0
  80. package/contracts/workers/dvn/src/lib.rs +6 -8
  81. package/contracts/workers/dvn/src/multisig.rs +98 -72
  82. package/contracts/workers/dvn/src/storage.rs +9 -12
  83. package/contracts/workers/dvn/src/tests/auth.rs +56 -26
  84. package/contracts/workers/dvn/src/tests/dvn.rs +40 -41
  85. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +8 -8
  86. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +9 -9
  87. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +6 -6
  88. package/contracts/workers/dvn/src/tests/setup.rs +5 -5
  89. package/contracts/workers/dvn-fee-lib/Cargo.toml +2 -1
  90. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +4 -3
  91. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +8 -6
  92. package/contracts/workers/executor/src/auth.rs +93 -0
  93. package/contracts/workers/executor/src/events.rs +5 -4
  94. package/contracts/workers/executor/src/{lz_executor.rs → executor.rs} +30 -103
  95. package/contracts/workers/executor/src/interfaces/executor.rs +5 -2
  96. package/contracts/workers/executor/src/interfaces/mod.rs +1 -1
  97. package/contracts/workers/executor/src/lib.rs +6 -5
  98. package/contracts/workers/price-feed/Cargo.toml +21 -0
  99. package/contracts/workers/price-feed/src/errors.rs +9 -0
  100. package/contracts/workers/price-feed/src/events.rs +30 -0
  101. package/contracts/workers/price-feed/src/lib.rs +11 -0
  102. package/contracts/workers/price-feed/src/price_feed.rs +265 -0
  103. package/contracts/workers/price-feed/src/storage.rs +42 -0
  104. package/contracts/workers/price-feed/src/types.rs +59 -0
  105. package/contracts/workers/worker/src/events.rs +23 -13
  106. package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +2 -1
  107. package/contracts/workers/worker/src/worker.rs +32 -21
  108. package/package.json +3 -3
  109. package/sdk/dist/generated/bml.js +24 -22
  110. package/sdk/dist/generated/counter.d.ts +102 -0
  111. package/sdk/dist/generated/counter.js +36 -24
  112. package/sdk/dist/generated/endpoint.js +24 -22
  113. package/sdk/dist/generated/sml.js +24 -22
  114. package/sdk/dist/generated/uln302.d.ts +1 -1
  115. package/sdk/dist/generated/uln302.js +34 -32
  116. package/sdk/package.json +1 -1
  117. package/sdk/test/index.test.ts +1 -1
  118. package/sdk/test/oft.test.ts +847 -0
  119. package/sdk/test/suites/scan.ts +20 -4
  120. package/tools/ts-bindings-gen/src/main.rs +2 -1
  121. package/contracts/common-macros/src/event.rs +0 -16
  122. package/contracts/oapps/oft/src/macro_tests/mod.rs +0 -2
  123. package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +0 -41
  124. package/contracts/oapps/oft/src/macro_tests/test_override.rs +0 -83
  125. package/contracts/oapps/oft-mint-burn/src/lib.rs +0 -3
  126. package/contracts/oapps/oft-mint-burn/src/oft.rs +0 -28
  127. package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +0 -1
  128. package/contracts/workers/dvn/src/types.rs +0 -26
  129. /package/contracts/message-libs/{block-message-lib → blocked-message-lib}/src/lib.rs +0 -0
@@ -0,0 +1,168 @@
1
+ use quote::quote;
2
+
3
+ use crate::tests::test_helpers::{assert_panics_contains, non_enum_item_inputs};
4
+
5
+ // ============================================
6
+ // Error Cases: Invalid Inputs
7
+ // ============================================
8
+
9
+ #[test]
10
+ fn test_contract_error_rejects_non_enum_inputs() {
11
+ for (case, input) in non_enum_item_inputs() {
12
+ assert_panics_contains(case, "failed to parse enum", || {
13
+ crate::error::generate_error(quote! {}, input.clone());
14
+ });
15
+ }
16
+ }
17
+
18
+ #[test]
19
+ fn test_contract_error_rejects_attr_arguments() {
20
+ let input = quote! {
21
+ pub enum MyError {
22
+ A,
23
+ }
24
+ };
25
+ assert_panics_contains("attr not empty", "contract_error attribute is not supported", || {
26
+ crate::error::generate_error(quote! { some_attr }, input);
27
+ });
28
+ }
29
+
30
+ #[test]
31
+ fn test_contract_error_requires_unit_variants() {
32
+ let cases = vec![("tuple variant", quote! { A(u32) }), ("struct variant", quote! { A { x: u32 } })];
33
+
34
+ for (case, variant) in cases {
35
+ let input = quote! {
36
+ pub enum MyError {
37
+ #variant,
38
+ }
39
+ };
40
+ assert_panics_contains(case, "Error enum variants must be unit variants", || {
41
+ crate::error::generate_error(quote! {}, input.clone());
42
+ });
43
+ }
44
+ }
45
+
46
+ #[test]
47
+ fn test_contract_error_discriminant_must_be_integer_literal() {
48
+ let cases = vec![
49
+ ("binary expr", quote! { 1 + 1 }),
50
+ ("path expr", quote! { SOME_CONST }),
51
+ ("negative integer (unary expr)", quote! { -1 }),
52
+ ("paren expr", quote! { (1) }),
53
+ ("bool literal", quote! { true }),
54
+ ("string literal", quote! { "1" }),
55
+ ("float literal", quote! { 1.0 }),
56
+ ("char literal", quote! { 'a' }),
57
+ ];
58
+
59
+ for (case, expr) in cases {
60
+ let input = quote! {
61
+ pub enum MyError {
62
+ A = #expr,
63
+ }
64
+ };
65
+ assert_panics_contains(case, "Error enum discriminant must be an integer literal", || {
66
+ crate::error::generate_error(quote! {}, input.clone());
67
+ });
68
+ }
69
+ }
70
+
71
+ #[test]
72
+ fn test_contract_error_discriminant_must_fit_u32() {
73
+ let input = quote! {
74
+ pub enum MyError {
75
+ A = 4294967296,
76
+ }
77
+ };
78
+
79
+ assert_panics_contains("u32::MAX + 1", "Error enum discriminant must be a valid u32 integer", || {
80
+ crate::error::generate_error(quote! {}, input);
81
+ });
82
+ }
83
+
84
+ #[test]
85
+ fn test_contract_error_discriminants_ordering_rejections_table_driven() {
86
+ let cases = vec![
87
+ (
88
+ "explicit value is less than previous",
89
+ quote! {
90
+ // A is assigned 1 by default; B cannot go backwards.
91
+ A,
92
+ B = 1,
93
+ },
94
+ ),
95
+ (
96
+ "explicit zero",
97
+ quote! {
98
+ A = 0,
99
+ },
100
+ ),
101
+ (
102
+ "explicit equal to previous explicit",
103
+ quote! {
104
+ A = 1,
105
+ B = 1,
106
+ },
107
+ ),
108
+ (
109
+ "explicit decreases after explicit",
110
+ quote! {
111
+ A = 5,
112
+ B = 4,
113
+ },
114
+ ),
115
+ ];
116
+
117
+ for (case, variants) in cases {
118
+ let input = quote! {
119
+ pub enum MyError {
120
+ #variants
121
+ }
122
+ };
123
+ assert_panics_contains(case, "Error enum discriminant must be greater than the previous discriminant", || {
124
+ crate::error::generate_error(quote! {}, input.clone());
125
+ });
126
+ }
127
+ }
128
+
129
+ #[test]
130
+ fn test_contract_error_max_not_last_panics_overflow() {
131
+ let input = quote! {
132
+ pub enum MyError {
133
+ A = 4294967295,
134
+ B,
135
+ }
136
+ };
137
+ assert_panics_contains("max not last overflows", "attempt to add with overflow", || {
138
+ crate::error::generate_error(quote! {}, input);
139
+ });
140
+ }
141
+
142
+ // ============================================
143
+ // Valid Cases: Snapshot Tests for Generated Code
144
+ // ============================================
145
+
146
+ #[test]
147
+ fn snapshot_generated_contract_error_code() {
148
+ let input = quote! {
149
+ /// Example error enum
150
+ pub enum MyError {
151
+ /// Implicit (should start at 1)
152
+ A,
153
+ /// Implicit (should be 2)
154
+ B,
155
+ /// Explicit (must be >= previous + 1)
156
+ C = 10,
157
+ /// Implicit (should be 11)
158
+ D,
159
+ /// Explicit max boundary (u32::MAX)
160
+ E = 4294967295,
161
+ }
162
+ };
163
+
164
+ let result = crate::error::generate_error(quote! {}, input);
165
+ let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
166
+
167
+ insta::assert_snapshot!(formatted);
168
+ }
@@ -1,9 +1,7 @@
1
1
  mod contract_impl;
2
+ mod error;
2
3
  mod ownable;
3
4
  mod storage;
4
5
  mod test_helpers;
5
6
  mod ttl_configurable;
6
-
7
- // Note: error.rs and event.rs use proc_macro::TokenStream which cannot be tested
8
- // outside of a procedural macro context. These macros are tested via integration
9
- // tests in the contracts that use them (e.g., utils crate).
7
+ mod utils;
@@ -19,15 +19,33 @@ fn snapshot_generated_ownable_code() {
19
19
 
20
20
  #[test]
21
21
  fn snapshot_only_owner_preserves_function_signature() {
22
- let input = quote! {
22
+ // Test with borrowed Env (&Env) - should use env directly
23
+ let input_borrowed = quote! {
23
24
  pub(crate) async fn admin_action<T: Clone>(env: &Env, value: T) -> Result<T, Error> {
24
25
  Ok(value.clone())
25
26
  }
26
27
  };
27
- let result = crate::ownable::prepend_only_owner_check(input);
28
- let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
28
+ let result_borrowed = crate::ownable::prepend_only_owner_check(input_borrowed);
29
+ let formatted_borrowed =
30
+ prettyplease::unparse(&syn::parse2::<syn::File>(result_borrowed).expect("failed to parse generated code"));
29
31
 
30
- insta::assert_snapshot!(formatted);
32
+ // Test with owned Env - should produce &env reference in the generated code
33
+ let input_owned = quote! {
34
+ pub(crate) async fn admin_action<T: Clone>(env: Env, value: T) -> Result<T, Error> {
35
+ Ok(value.clone())
36
+ }
37
+ };
38
+ let result_owned = crate::ownable::prepend_only_owner_check(input_owned);
39
+ let formatted_owned =
40
+ prettyplease::unparse(&syn::parse2::<syn::File>(result_owned).expect("failed to parse generated code"));
41
+
42
+ // Combine all for single snapshot
43
+ let combined = format!(
44
+ "// === Borrowed Env (&Env) ===\n\n{}\n\n// === Owned Env (Env) ===\n\n{}",
45
+ formatted_borrowed, formatted_owned
46
+ );
47
+
48
+ insta::assert_snapshot!(combined);
31
49
  }
32
50
 
33
51
  // ============================================
@@ -35,7 +53,7 @@ fn snapshot_only_owner_preserves_function_signature() {
35
53
  // ============================================
36
54
 
37
55
  /// Helper function to verify that the owner check is correctly inserted at the beginning of a function.
38
- fn assert_owner_check_inserted(input: TokenStream, test_name: &str) {
56
+ fn assert_owner_check_inserted(input: TokenStream, expected_env_ref: &str, test_name: &str) {
39
57
  let result_tokens = crate::ownable::prepend_only_owner_check(input);
40
58
  let output_fn: syn::ItemFn =
41
59
  syn::parse2(result_tokens).unwrap_or_else(|e| panic!("{}: failed to parse output function: {}", test_name, e));
@@ -43,7 +61,7 @@ fn assert_owner_check_inserted(input: TokenStream, test_name: &str) {
43
61
  assert!(!output_fn.block.stmts.is_empty(), "{}: function body should contain at least one statement", test_name);
44
62
 
45
63
  let first_stmt = &output_fn.block.stmts[0];
46
- let expected_stmt = "utils::ownable::require_owner_auth::<Self>(my_custom_env);";
64
+ let expected_stmt = format!("utils::ownable::require_owner_auth::<Self>({});", expected_env_ref);
47
65
  let actual_stmt = quote::quote!(#first_stmt).to_string().replace(" ", "");
48
66
 
49
67
  assert_eq!(
@@ -55,15 +73,22 @@ fn assert_owner_check_inserted(input: TokenStream, test_name: &str) {
55
73
 
56
74
  #[test]
57
75
  fn test_only_owner_inserts_correct_code_at_the_beginning() {
76
+ // (description, input, expected_env_ref)
77
+ // Owned Env should produce &env, reference Env should produce env directly
58
78
  let test_cases = vec![
59
- ("Env by value", quote! { pub fn f(my_custom_env: Env) {} }),
60
- ("Env not first param", quote! { pub fn f(x: u32, my_custom_env: &Env) {} }),
61
- ("Qualified path (soroban_sdk::Env)", quote! { pub fn f(my_custom_env: soroban_sdk::Env) {} }),
62
- ("Nested reference (&&Env)", quote! { pub fn f(my_custom_env: &&Env) {} }),
79
+ ("Env by value", quote! { pub fn f(my_custom_env: Env) {} }, "&my_custom_env"),
80
+ ("Env not first param (ref)", quote! { pub fn f(x: u32, my_custom_env: &Env) {} }, "my_custom_env"),
81
+ (
82
+ "Qualified path (soroban_sdk::Env)",
83
+ quote! { pub fn f(my_custom_env: soroban_sdk::Env) {} },
84
+ "&my_custom_env",
85
+ ),
86
+ ("Reference to qualified path", quote! { pub fn f(my_custom_env: &soroban_sdk::Env) {} }, "my_custom_env"),
87
+ ("Nested reference (&&Env)", quote! { pub fn f(my_custom_env: &&Env) {} }, "my_custom_env"),
63
88
  ];
64
89
 
65
- for (description, input) in test_cases {
66
- assert_owner_check_inserted(input, description);
90
+ for (description, input, expected_env_ref) in test_cases {
91
+ assert_owner_check_inserted(input, expected_env_ref, description);
67
92
  }
68
93
  }
69
94
 
@@ -101,51 +126,3 @@ fn test_ownable_rejects_non_struct_inputs() {
101
126
  });
102
127
  }
103
128
  }
104
-
105
- // ============================================
106
- // is_env_type Unit Tests
107
- // ============================================
108
-
109
- #[test]
110
- fn test_is_env_type_recognizes_env_types() {
111
- let env_types = [
112
- "Env",
113
- "&Env",
114
- "&&Env",
115
- "&mut Env",
116
- "soroban_sdk::Env",
117
- "&soroban_sdk::Env",
118
- "some::deeply::nested::module::Env",
119
- ];
120
-
121
- for ty_str in env_types {
122
- let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
123
- assert!(crate::utils::is_env_type(&ty), "{ty_str} should be recognized as an Env type");
124
- }
125
- }
126
-
127
- #[test]
128
- fn test_is_env_type_rejects_non_env_types() {
129
- let non_env_types = ["u32", "bool", "String", "Address", "&u32", "soroban_sdk::Address"];
130
-
131
- for ty_str in non_env_types {
132
- let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
133
- assert!(!crate::utils::is_env_type(&ty), "{ty_str} should NOT be recognized as an Env type");
134
- }
135
- }
136
-
137
- #[test]
138
- fn test_is_env_type_rejects_other_type_variants() {
139
- let other_variants = [
140
- ("(Env, u32)", "tuple"),
141
- ("[Env; 1]", "array"),
142
- ("[Env]", "slice"),
143
- ("Option<Env>", "generic"),
144
- ("!", "never"),
145
- ];
146
-
147
- for (ty_str, label) in other_variants {
148
- let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
149
- assert!(!crate::utils::is_env_type(&ty), "{label} type {ty_str} should NOT be recognized as an Env type");
150
- }
151
- }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  source: contracts/common-macros/src/tests/contract_impl.rs
3
- assertion_line: 98
3
+ assertion_line: 104
4
4
  expression: combined
5
5
  ---
6
6
  // === Inherent Impl (no attr) ===
@@ -9,7 +9,7 @@ expression: combined
9
9
  impl MyContract {
10
10
  /// Public method with Env - should have TTL extension
11
11
  pub fn public_with_env(env: Env, value: u32) -> u32 {
12
- if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(env) {
12
+ if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(&env) {
13
13
  env.storage()
14
14
  .instance()
15
15
  .extend_ttl(instance_ttl.threshold, instance_ttl.extend_to);
@@ -18,7 +18,7 @@ impl MyContract {
18
18
  }
19
19
  /// Public method with qualified Env path - should have TTL extension
20
20
  pub fn with_qualified_env(env: soroban_sdk::Env) -> u32 {
21
- if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(env) {
21
+ if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(&env) {
22
22
  env.storage()
23
23
  .instance()
24
24
  .extend_ttl(instance_ttl.threshold, instance_ttl.extend_to);
@@ -26,7 +26,7 @@ impl MyContract {
26
26
  42
27
27
  }
28
28
  /// Public method with Env not as first parameter - should have TTL extension
29
- pub fn env_second(value: u32, env: Env) -> u32 {
29
+ pub fn env_second(value: u32, env: &Env) -> u32 {
30
30
  if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(env) {
31
31
  env.storage()
32
32
  .instance()
@@ -55,7 +55,7 @@ impl MyContract {
55
55
  impl SomeTrait for MyContract {
56
56
  /// Trait method with Env - should have TTL extension
57
57
  fn trait_method_with_env(env: Env, value: u32) -> u32 {
58
- if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(env) {
58
+ if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(&env) {
59
59
  env.storage()
60
60
  .instance()
61
61
  .extend_ttl(instance_ttl.threshold, instance_ttl.extend_to);
@@ -66,6 +66,16 @@ impl SomeTrait for MyContract {
66
66
  fn trait_method_without_env(value: u32) -> u32 {
67
67
  value * 4
68
68
  }
69
+ /// Trait method with macro attribute - should have TTL extension
70
+ #[common_macros::only_owner]
71
+ fn trait_method_with_only_owner_attribute(env: Env, value: u32) -> u32 {
72
+ if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(&env) {
73
+ env.storage()
74
+ .instance()
75
+ .extend_ttl(instance_ttl.threshold, instance_ttl.extend_to);
76
+ }
77
+ value * 5
78
+ }
69
79
  }
70
80
 
71
81
 
@@ -74,7 +84,7 @@ impl SomeTrait for MyContract {
74
84
  #[soroban_sdk::contractimpl(contracttrait)]
75
85
  impl AnotherTrait for MyContract {
76
86
  /// Trait method with contracttrait attr - should have TTL extension
77
- fn contracttrait_method(env: Env, value: u32) -> u32 {
87
+ fn contracttrait_method(env: &Env, value: u32) -> u32 {
78
88
  if let Some(instance_ttl) = utils::ttl::TtlConfigStorage::instance(env) {
79
89
  env.storage()
80
90
  .instance()
@@ -0,0 +1,20 @@
1
+ ---
2
+ source: contracts/common-macros/src/tests/error.rs
3
+ expression: formatted
4
+ ---
5
+ #[soroban_sdk::contracterror]
6
+ #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
7
+ #[repr(u32)]
8
+ /// Example error enum
9
+ pub enum MyError {
10
+ /// Implicit (should start at 1)
11
+ A = 1u32,
12
+ /// Implicit (should be 2)
13
+ B = 2u32,
14
+ /// Explicit (must be >= previous + 1)
15
+ C = 10,
16
+ /// Implicit (should be 11)
17
+ D = 11u32,
18
+ /// Explicit max boundary (u32::MAX)
19
+ E = 4294967295,
20
+ }
@@ -16,14 +16,16 @@ impl utils::ownable::OwnableInitializer for MyContract {
16
16
  }
17
17
  }
18
18
  /// Implement the Ownable trait for the contract.
19
- #[soroban_sdk::contractimpl]
19
+ #[common_macros::contract_impl]
20
20
  impl utils::ownable::Ownable for MyContract {
21
21
  fn owner(env: &soroban_sdk::Env) -> Option<soroban_sdk::Address> {
22
22
  utils::ownable::DefaultOwnable::owner(env)
23
23
  }
24
+ #[common_macros::only_owner]
24
25
  fn transfer_ownership(env: &soroban_sdk::Env, new_owner: &soroban_sdk::Address) {
25
26
  utils::ownable::DefaultOwnable::transfer_ownership(env, new_owner)
26
27
  }
28
+ #[common_macros::only_owner]
27
29
  fn renounce_ownership(env: &soroban_sdk::Env) {
28
30
  utils::ownable::DefaultOwnable::renounce_ownership(env)
29
31
  }
@@ -1,9 +1,19 @@
1
1
  ---
2
2
  source: contracts/common-macros/src/tests/ownable.rs
3
- assertion_line: 28
4
- expression: formatted
3
+ assertion_line: 48
4
+ expression: combined
5
5
  ---
6
+ // === Borrowed Env (&Env) ===
7
+
6
8
  pub(crate) async fn admin_action<T: Clone>(env: &Env, value: T) -> Result<T, Error> {
7
9
  utils::ownable::require_owner_auth::<Self>(env);
8
10
  Ok(value.clone())
9
11
  }
12
+
13
+
14
+ // === Owned Env (Env) ===
15
+
16
+ pub(crate) async fn admin_action<T: Clone>(env: Env, value: T) -> Result<T, Error> {
17
+ utils::ownable::require_owner_auth::<Self>(&env);
18
+ Ok(value.clone())
19
+ }
@@ -8,7 +8,7 @@ pub struct MyContract {
8
8
  some_field: u32,
9
9
  }
10
10
  use utils::ttl::TtlConfigurable as _;
11
- #[soroban_sdk::contractimpl]
11
+ #[common_macros::contract_impl]
12
12
  impl utils::ttl::TtlConfigurable for MyContract {
13
13
  #[common_macros::only_owner]
14
14
  fn set_ttl_configs(
@@ -31,6 +31,10 @@ impl utils::ttl::TtlConfigurable for MyContract {
31
31
  utils::ttl::DefaultTtlConfigurable::is_ttl_configs_frozen(env)
32
32
  }
33
33
  }
34
+ /// Uses `soroban_sdk::contractimpl` directly instead of `common_macros::contract_impl`
35
+ /// because `contract_impl` automatically extends TTL on every invocation. Since this
36
+ /// impl block provides manual TTL extension control, auto-extension would be redundant
37
+ /// and could mask the intended behavior of `extend_instance_ttl`.
34
38
  #[soroban_sdk::contractimpl]
35
39
  impl MyContract {
36
40
  /// Extends the instance TTL.