@layerzerolabs/framework-solana-anchor-trait 0.2.81 → 0.2.82

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.
@@ -89,9 +89,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
89
89
 
90
90
  [[package]]
91
91
  name = "anchor-attribute-access-control"
92
- version = "1.0.0"
92
+ version = "1.0.1"
93
93
  source = "registry+https://github.com/rust-lang/crates.io-index"
94
- checksum = "b972f5fbd02524c92e4eb487c3c648904572702670f3d6fc81aef5f1751b1569"
94
+ checksum = "fe55cad36a574c8a048bd4be3f24f438f1888d78098bc137370dab4f6e2173c6"
95
95
  dependencies = [
96
96
  "proc-macro2",
97
97
  "quote",
@@ -100,9 +100,9 @@ dependencies = [
100
100
 
101
101
  [[package]]
102
102
  name = "anchor-attribute-account"
103
- version = "1.0.0"
103
+ version = "1.0.1"
104
104
  source = "registry+https://github.com/rust-lang/crates.io-index"
105
- checksum = "9acfcb07a92084bcfa9f6cc49a5c2e8e0e986f25f4b7caa184b7a2c9c9e561c2"
105
+ checksum = "4624a1addfa17ef75c5d1eae33b724848420befba0f4f270562daba22704f933"
106
106
  dependencies = [
107
107
  "anchor-syn",
108
108
  "proc-macro2",
@@ -112,9 +112,9 @@ dependencies = [
112
112
 
113
113
  [[package]]
114
114
  name = "anchor-attribute-constant"
115
- version = "1.0.0"
115
+ version = "1.0.1"
116
116
  source = "registry+https://github.com/rust-lang/crates.io-index"
117
- checksum = "8f46cc38f819377f07663b8eb492a701427950065e79d2d7b622a782443deb7a"
117
+ checksum = "4043728a3a9f9cd77165d1631d859f22536a5309545ea9803cdabf7eb541af50"
118
118
  dependencies = [
119
119
  "anchor-syn",
120
120
  "quote",
@@ -123,9 +123,9 @@ dependencies = [
123
123
 
124
124
  [[package]]
125
125
  name = "anchor-attribute-error"
126
- version = "1.0.0"
126
+ version = "1.0.1"
127
127
  source = "registry+https://github.com/rust-lang/crates.io-index"
128
- checksum = "9c34748789107c9838329e058ca7b253e67f37b39ceae5a0a6c8d99f5d1bf1fe"
128
+ checksum = "082f60f03c2dd9c9df1997b9b83ce66e409a46ed701d3e17c157c69006f4058c"
129
129
  dependencies = [
130
130
  "anchor-syn",
131
131
  "quote",
@@ -134,9 +134,9 @@ dependencies = [
134
134
 
135
135
  [[package]]
136
136
  name = "anchor-attribute-event"
137
- version = "1.0.0"
137
+ version = "1.0.1"
138
138
  source = "registry+https://github.com/rust-lang/crates.io-index"
139
- checksum = "1a28a3e5eefa03d9c5ef02b2139198f652547d38dddafc9c5545152dfba54556"
139
+ checksum = "f7d4cfbfea47ca95da8a7558dd058414e0db563cc56b609e8aa90d41d96c1509"
140
140
  dependencies = [
141
141
  "anchor-syn",
142
142
  "proc-macro2",
@@ -146,9 +146,9 @@ dependencies = [
146
146
 
147
147
  [[package]]
148
148
  name = "anchor-attribute-program"
149
- version = "1.0.0"
149
+ version = "1.0.1"
150
150
  source = "registry+https://github.com/rust-lang/crates.io-index"
151
- checksum = "dfaa03865053cb168bfc4debe5992be87f397aa027dd81b69a2e44f2e5bae1c5"
151
+ checksum = "6050e980111673736783492b56da3833628ae9af123bc125d2b5f492f65b9ec8"
152
152
  dependencies = [
153
153
  "anchor-lang-idl",
154
154
  "anchor-syn",
@@ -161,9 +161,9 @@ dependencies = [
161
161
 
162
162
  [[package]]
163
163
  name = "anchor-derive-accounts"
164
- version = "1.0.0"
164
+ version = "1.0.1"
165
165
  source = "registry+https://github.com/rust-lang/crates.io-index"
166
- checksum = "eef330db08f9ceee45c18ef96b15b869883d280c0ab5c6ff5d2e2f6481da7911"
166
+ checksum = "b85ae71b15fcd02c1527bca8bd088cc4cdf1c664fdebf0dad3f1d6d454a2eefa"
167
167
  dependencies = [
168
168
  "anchor-syn",
169
169
  "quote",
@@ -172,9 +172,9 @@ dependencies = [
172
172
 
173
173
  [[package]]
174
174
  name = "anchor-derive-serde"
175
- version = "1.0.0"
175
+ version = "1.0.1"
176
176
  source = "registry+https://github.com/rust-lang/crates.io-index"
177
- checksum = "e0e80ff4e3ddb8c85aafd37926335c28f820516311e7106e5b7482b42e798aaa"
177
+ checksum = "826334d127a2ccaed18c1d74c69b8b00cb0e17f99f01b66c92ac108c4792e126"
178
178
  dependencies = [
179
179
  "anchor-syn",
180
180
  "proc-macro-crate",
@@ -185,9 +185,9 @@ dependencies = [
185
185
 
186
186
  [[package]]
187
187
  name = "anchor-derive-space"
188
- version = "1.0.0"
188
+ version = "1.0.1"
189
189
  source = "registry+https://github.com/rust-lang/crates.io-index"
190
- checksum = "2672af0ef4dfd5f5b6199355867b580cd8b4048093ef5208dd2b441305c15b8b"
190
+ checksum = "7b128347e1a8d8f8c14942467a1251e861095c56fe9b7d7f2af09b3f89f7c9a3"
191
191
  dependencies = [
192
192
  "proc-macro2",
193
193
  "quote",
@@ -196,9 +196,9 @@ dependencies = [
196
196
 
197
197
  [[package]]
198
198
  name = "anchor-lang"
199
- version = "1.0.0"
199
+ version = "1.0.1"
200
200
  source = "registry+https://github.com/rust-lang/crates.io-index"
201
- checksum = "8de9dce227fa0c08be20fef008c5b04681e1e0a15cb396e9619a9a1f800ff6cd"
201
+ checksum = "df469a8bc353440c577504444fc8f53f9f139e61f03981897ecd3e818e8cb3ae"
202
202
  dependencies = [
203
203
  "anchor-attribute-access-control",
204
204
  "anchor-attribute-account",
@@ -266,9 +266,9 @@ dependencies = [
266
266
 
267
267
  [[package]]
268
268
  name = "anchor-syn"
269
- version = "1.0.0"
269
+ version = "1.0.1"
270
270
  source = "registry+https://github.com/rust-lang/crates.io-index"
271
- checksum = "c62f42cb7e348c033bd9bfba59979bcd66431c026ba23490af94045aa357a950"
271
+ checksum = "3dba8b3c2a352142721a10745bcf1db94bc1dfdc9b313128b6ef5cac4f2be1b4"
272
272
  dependencies = [
273
273
  "anyhow",
274
274
  "bs58",
@@ -3,7 +3,7 @@ members = ["programs/ellipse", "programs/triangle", "macros"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.dependencies]
6
- anchor-lang = "1.0.0"
6
+ anchor-lang = { version = "1.0.1" }
7
7
  anchor-trait = { path = "../.." }
8
8
  shapes-macros = { path = "macros" }
9
9
  mollusk-svm = { version = "0.8", features = ["inner-instructions"] }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layerzerolabs/framework-solana-anchor-trait",
3
- "version": "0.2.81",
3
+ "version": "0.2.82",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,10 +14,10 @@
14
14
  "rustfmt.toml"
15
15
  ],
16
16
  "devDependencies": {
17
- "@layerzerolabs/build-utils-solana": "0.2.81",
18
- "@layerzerolabs/tsup-configuration": "0.2.81",
19
- "@layerzerolabs/typescript-configuration": "0.2.81",
20
- "@layerzerolabs/vm-tooling-solana": "0.2.81"
17
+ "@layerzerolabs/tsup-configuration": "0.2.82",
18
+ "@layerzerolabs/typescript-configuration": "0.2.82",
19
+ "@layerzerolabs/vm-tooling-solana": "0.2.82",
20
+ "@layerzerolabs/build-utils-solana": "0.2.82"
21
21
  },
22
22
  "publishConfig": {
23
23
  "access": "restricted",
package/src/assembly.rs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  use proc_macro2::{Ident, TokenStream};
4
4
  use quote::quote;
5
- use syn::ItemMod;
5
+ use syn::{AttrStyle, ItemMod};
6
6
 
7
7
  use crate::{generation::GeneratedInstructions, overrides::InstructionOverrides, InstructionSet};
8
8
 
@@ -38,10 +38,11 @@ impl<Ix: InstructionSet> Assembly<Ix> {
38
38
  /// wrapper_defs // relocated override handler modules
39
39
  /// default_impls // generated default accounts structs + handler impls
40
40
  /// extend_macro // macro_rules! for extending default accounts (if configured)
41
- /// #[original_mod_attrs]
41
+ /// #[outer_mod_attrs] // outer attrs from the source module
42
42
  /// #[extra_mod_attrs] // e.g. #[rbac(...)]
43
43
  /// #[program] // always innermost — auto-managed by Assembly
44
44
  /// mod name {
45
+ /// #![inner_mod_attrs] // inner attrs from the source module (e.g. #![deny(...)])
45
46
  /// filtered_items // original items minus relocated handlers
46
47
  /// entrypoints // generated instruction entrypoints
47
48
  /// }
@@ -73,9 +74,11 @@ impl<Ix: InstructionSet> Assembly<Ix> {
73
74
 
74
75
  let ItemMod { attrs: mod_attrs, vis: mod_vis, ident: mod_ident, .. } = &source_mod;
75
76
 
76
- // Filter out #[program] attribute if it is already present.
77
- let mod_attrs: Vec<_> =
78
- mod_attrs.iter().filter(|a| !a.path().is_ident("program")).collect();
77
+ // Inner attrs (`#![...]`, `//!`) must live inside the body — rustc rejects them outside.
78
+ let (inner_attrs, outer_attrs): (Vec<_>, Vec<_>) = mod_attrs
79
+ .iter()
80
+ .filter(|a| a.path().segments.last().is_none_or(|s| s.ident != "program"))
81
+ .partition(|a| matches!(a.style, AttrStyle::Inner(_)));
79
82
 
80
83
  quote! {
81
84
  #prelude
@@ -83,10 +86,11 @@ impl<Ix: InstructionSet> Assembly<Ix> {
83
86
  #default_impls
84
87
  #extend_macro
85
88
 
86
- #(#mod_attrs)*
89
+ #(#outer_attrs)*
87
90
  #extra_mod_attrs
88
91
  #[program]
89
92
  #mod_vis mod #mod_ident {
93
+ #(#inner_attrs)*
90
94
  use super::*;
91
95
  #filtered_items
92
96
  #entrypoints
package/src/overrides.rs CHANGED
@@ -176,7 +176,7 @@ fn has_override_attr(fn_item: &ItemFn, cfg: OverrideConfig) -> bool {
176
176
 
177
177
  /// Returns `true` if `attr`'s last path segment matches the configured attribute name.
178
178
  fn is_override_attr(attr: &Attribute, cfg: OverrideConfig) -> bool {
179
- attr.path().is_ident(cfg.attr_name)
179
+ attr.path().segments.last().is_some_and(|s| s.ident == cfg.attr_name)
180
180
  }
181
181
 
182
182
  /// Parses the override target from a function's override attribute.
package/tests/assembly.rs CHANGED
@@ -161,6 +161,126 @@ mod tests {
161
161
  assert!(has_custom_attr, "original module attributes should be preserved");
162
162
  }
163
163
 
164
+ #[test]
165
+ fn inner_attrs_routed_into_module_body() {
166
+ // Inner attributes (#![...]) and inner doc comments (//!) on the source module
167
+ // must end up inside the generated mod's body, not outside, otherwise rustc
168
+ // rejects them with "an inner attribute is not permitted in this context".
169
+ let module: syn::ItemMod = syn::parse_quote! {
170
+ mod my_program {
171
+ #![deny(clippy::arithmetic_side_effects)]
172
+ #![allow(unused_variables)]
173
+ //! Module-level doc comment.
174
+
175
+ #[test_instruction]
176
+ pub fn lz_receive(ctx: &mut Context<MyReceive>, params: &LzReceiveParams) -> Result<()> {
177
+ Ok(())
178
+ }
179
+ }
180
+ };
181
+ let file = assemble_ok(&module, quote! {}, quote! {});
182
+ let (_, m) = find_program_mod(&file).expect("module should exist");
183
+
184
+ let inner_attrs: Vec<_> =
185
+ m.attrs.iter().filter(|a| matches!(a.style, syn::AttrStyle::Inner(_))).collect();
186
+
187
+ let has_deny = inner_attrs
188
+ .iter()
189
+ .any(|a| a.path().segments.last().is_some_and(|seg| seg.ident == "deny"));
190
+ let has_allow = inner_attrs
191
+ .iter()
192
+ .any(|a| a.path().segments.last().is_some_and(|seg| seg.ident == "allow"));
193
+ let has_inner_doc = inner_attrs
194
+ .iter()
195
+ .any(|a| a.path().segments.last().is_some_and(|seg| seg.ident == "doc"));
196
+
197
+ assert!(
198
+ has_deny,
199
+ "#![deny(...)] should be preserved as an inner attr on the generated mod"
200
+ );
201
+ assert!(
202
+ has_allow,
203
+ "#![allow(...)] should be preserved as an inner attr on the generated mod"
204
+ );
205
+ assert!(
206
+ has_inner_doc,
207
+ "//! doc comment should be preserved as an inner attr on the generated mod"
208
+ );
209
+
210
+ // Sanity: no inner-style attribute should appear *before* the generated mod —
211
+ // that would be exactly the position rustc rejects.
212
+ let rendered = quote!(#file).to_string();
213
+ let mod_token = format!("mod {}", m.ident);
214
+ let prefix = rendered
215
+ .split(&mod_token)
216
+ .next()
217
+ .expect("rendered output should contain the module");
218
+ assert!(
219
+ !prefix.contains("# ! ["),
220
+ "no inner-style attribute (#![...]) should appear before the generated mod;\n\
221
+ prefix was:\n{prefix}"
222
+ );
223
+ }
224
+
225
+ #[test]
226
+ fn qualified_program_attr_is_deduplicated() {
227
+ // A previously-expanded macro may have placed a qualified #[program] on the
228
+ // source module (e.g. `#[anchor_lang::prelude::program]`). Assembly always
229
+ // re-emits a canonical `#[program]`, so the qualified form must be filtered
230
+ // out — otherwise the generated module carries two `#[program]` attributes
231
+ // and Anchor's program macro would expand twice.
232
+ let module: syn::ItemMod = syn::parse_quote! {
233
+ #[anchor_lang::prelude::program]
234
+ mod my_program {
235
+ #[test_instruction]
236
+ pub fn lz_receive(ctx: &mut Context<MyReceive>, params: &LzReceiveParams) -> Result<()> {
237
+ Ok(())
238
+ }
239
+ }
240
+ };
241
+ let file = assemble_ok(&module, quote! {}, quote! {});
242
+ let (_, m) = find_program_mod(&file).expect("module should exist");
243
+
244
+ let program_attr_count = m
245
+ .attrs
246
+ .iter()
247
+ .filter(|a| a.path().segments.last().is_some_and(|s| s.ident == "program"))
248
+ .count();
249
+ assert_eq!(
250
+ program_attr_count, 1,
251
+ "exactly one #[program] attr should remain on the generated mod"
252
+ );
253
+ }
254
+
255
+ #[test]
256
+ fn outer_and_inner_attrs_partitioned_correctly() {
257
+ let module: syn::ItemMod = syn::parse_quote! {
258
+ #[some_outer_attr]
259
+ mod my_program {
260
+ #![deny(clippy::arithmetic_side_effects)]
261
+
262
+ #[test_instruction]
263
+ pub fn lz_receive(ctx: &mut Context<MyReceive>, params: &LzReceiveParams) -> Result<()> {
264
+ Ok(())
265
+ }
266
+ }
267
+ };
268
+ let file = assemble_ok(&module, quote! {}, quote! {});
269
+ let (_, m) = find_program_mod(&file).expect("module should exist");
270
+
271
+ let has_outer = m.attrs.iter().any(|a| {
272
+ matches!(a.style, syn::AttrStyle::Outer)
273
+ && a.path().segments.last().is_some_and(|seg| seg.ident == "some_outer_attr")
274
+ });
275
+ let has_inner_deny = m.attrs.iter().any(|a| {
276
+ matches!(a.style, syn::AttrStyle::Inner(_))
277
+ && a.path().segments.last().is_some_and(|seg| seg.ident == "deny")
278
+ });
279
+
280
+ assert!(has_outer, "outer attribute should be preserved on the generated mod");
281
+ assert!(has_inner_deny, "inner attribute should be preserved on the generated mod");
282
+ }
283
+
164
284
  #[test]
165
285
  fn filtered_items_inside_module() {
166
286
  let module = module_with_override_and_extras();
package/tests/override.rs CHANGED
@@ -121,6 +121,28 @@ mod tests {
121
121
  assert!(overrides.get(TestIx::LzReceive).is_none());
122
122
  }
123
123
 
124
+ #[test]
125
+ fn qualified_attribute_path_recognized_as_override() {
126
+ // A qualified attribute path like `#[crate::test_instruction]` should still
127
+ // register as an override. `Path::is_ident` is strict-1-segment and would
128
+ // silently miss this, leaving the function as a bare item and emitting the
129
+ // default entrypoint instead.
130
+ let module: syn::ItemMod = syn::parse_quote! {
131
+ mod my_program {
132
+ #[crate::test_instruction]
133
+ pub fn set_peer(ctx: &mut Context<MyAccounts>, params: &SetPeerParams) -> Result<()> {
134
+ Ok(())
135
+ }
136
+ }
137
+ };
138
+ let overrides = collect_ok(&module);
139
+
140
+ assert!(
141
+ overrides.get(TestIx::SetPeer).is_some(),
142
+ "qualified #[crate::test_instruction] should register as a SetPeer override"
143
+ );
144
+ }
145
+
124
146
  #[test]
125
147
  fn multiple_unique_overrides() {
126
148
  let module: syn::ItemMod = syn::parse_quote! {