@layerzerolabs/oapp-solana-contracts 1.2.72 → 1.2.74

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.
package/Anchor.toml CHANGED
@@ -1,18 +1,14 @@
1
1
  [toolchain]
2
- anchor_version = "1.1.2"
3
- solana_version = "3.1.10"
2
+ anchor_version = "1.2.1"
3
+ solana_version = "4.3.0"
4
4
 
5
5
  [features]
6
- seeds = false
7
6
  skip-lint = false
8
7
  resolution = false
9
8
 
10
9
  [programs.localnet]
11
10
  counter = "Cnt11111111111111111111111111111111111111111"
12
11
 
13
- [registry]
14
- url = "https://api.apr.dev"
15
-
16
12
  [provider]
17
13
  cluster = "Localnet"
18
14
  wallet = "~/.config/solana/id.json"
package/Cargo.toml CHANGED
@@ -19,8 +19,8 @@ idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build", "oapp-macros/idl-b
19
19
  unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
20
20
 
21
21
  [dependencies]
22
- anchor-lang = { version = "1.1.2" }
23
- anchor-spl = { version = "1.1.2" }
22
+ anchor-lang = { version = "1.2.1", default-features = false, features = ["solana-v4"] }
23
+ anchor-spl = { version = "1.2.1", default-features = false, features = ["associated_token", "mint", "token", "token_2022", "token_2022_extensions", "solana-v4"] }
24
24
  oapp-macros = { path = "macros" }
25
25
  solana-keccak-hasher = "3.1.0"
26
26
  spl-type-length-value = { version = "0.9.1", features = ["derive"] }
package/README.md CHANGED
@@ -55,22 +55,22 @@ Every OApp program exposes a standard set of instructions, generated by the `#[o
55
55
 
56
56
  Generated by the `#[oapp]` attribute macro from `oapp`.
57
57
 
58
- | Instruction | View | Has Default | Description |
59
- | ----------------------- | ---- | ----------- | ---------------------------------------------------------- |
60
- | `set_peer` | No | Yes | Register a trusted remote OApp |
61
- | `get_peer` | Yes | Yes | Read registered peer address |
62
- | `init_enforced_options` | No | Yes | Create the EnforcedOptions PDA with initial options buffer |
63
- | `set_enforced_options` | No | Yes | Update enforced send options (with resize) |
64
- | `get_enforced_options` | Yes | Yes | Read enforced options |
65
- | `next_nonce` | Yes | Yes | Read next inbound nonce |
66
- | `is_compose_msg_sender` | Yes | Yes | Validate compose message sender |
67
- | `lz_receive_types_info` | Yes | No | Return LzReceiveTypes version and accounts |
68
- | `lz_receive_types_v3` | No | No | Write the lz_receive execution plan to caller scratch |
69
- | `lz_receive` | No | No | Execute inbound cross-chain message |
70
- | `clear` | No | Yes | Consume a verified inbound message without `lz_receive` |
71
- | `skip` | No | Yes | Skip the next inbound nonce |
72
- | `burn` | No | Yes | Permanently burn a verified inbound payload |
73
- | `nilify` | No | Yes | Block an inbound nonce until it is re-verified |
58
+ | Instruction | View | Has Default | Description |
59
+ | ----------------------- | ---- | ----------- | ------------------------------------------------------------------ |
60
+ | `set_peer` | No | Yes | Register a trusted remote OApp |
61
+ | `get_peer` | Yes | Yes | Read registered peer address |
62
+ | `init_enforced_options` | No | Yes | Create the EnforcedOptions PDA with initial options buffer |
63
+ | `set_enforced_options` | No | Yes | Update enforced send options (with resize) |
64
+ | `get_enforced_options` | Yes | Yes | Read enforced options |
65
+ | `next_nonce` | Yes | Yes | Next nonce for ordered delivery; the default returns 0 (unordered) |
66
+ | `is_compose_msg_sender` | Yes | Yes | Validate compose message sender |
67
+ | `lz_receive_types_info` | Yes | No | Return LzReceiveTypes version and accounts |
68
+ | `lz_receive_types_v3` | No | No | Write the lz_receive execution plan to caller scratch |
69
+ | `lz_receive` | No | No | Execute inbound cross-chain message |
70
+ | `clear` | No | Yes | Consume a verified inbound message without `lz_receive` |
71
+ | `skip` | No | Yes | Skip the next unverified inbound nonce |
72
+ | `burn` | No | Yes | Permanently burn a verified payload at or below the inbound nonce |
73
+ | `nilify` | No | Yes | Block an inbound nonce until it is re-verified |
74
74
 
75
75
  ### RBAC Instructions
76
76
 
package/macros/Cargo.toml CHANGED
@@ -11,7 +11,7 @@ default = []
11
11
  idl-build = ["anchor-lang/idl-build"]
12
12
 
13
13
  [dependencies]
14
- anchor-lang = { version = "1.1.2" }
14
+ anchor-lang = { version = "1.2.1", default-features = false, features = ["solana-v4"] }
15
15
  anchor-trait = { path = "../dependencies/framework-solana-anchor-trait" }
16
16
  syn = { version = "2.0", features = ["full", "parsing", "extra-traits"] }
17
17
  quote = "1.0"
@@ -35,7 +35,8 @@ fn generate_default_impl(
35
35
 
36
36
  #[account(
37
37
  seeds = [::oapp::NONCE_SEED, oapp.key().as_ref(), &params.src_eid.to_be_bytes(), &params.sender],
38
- bump
38
+ bump,
39
+ seeds::program = ::oapp::endpoint::ID
39
40
  )]
40
41
  pub nonce_account: UncheckedAccount<'info>,
41
42
  }
package/macros/src/lib.rs CHANGED
@@ -75,6 +75,25 @@ pub fn composer(attr: TokenStream, item: TokenStream) -> TokenStream {
75
75
  /// The body of this stub is unreachable: `#[composer]` consumes the enclosing
76
76
  /// module token stream and strips this marker before rustc sees it.
77
77
  /// Override logic lives in `composer::expand`.
78
+ ///
79
+ /// # Security: `lz_compose`
80
+ ///
81
+ /// The handler MUST verify that `params.from` is an OApp it trusts. Anyone can
82
+ /// queue a compose message with the Endpoint's `send_compose`, which records
83
+ /// its signer as `from`; `clear_compose` only proves the message came from
84
+ /// `params.from`, not that the sender is trusted. Bind the trusted sender
85
+ /// (e.g. the OFT store whose receives queue these messages) in the composer's
86
+ /// state and check it declaratively:
87
+ ///
88
+ /// ```ignore
89
+ /// #[account(
90
+ /// seeds = [COMPOSER_SEED],
91
+ /// bump = composer_store.bump,
92
+ /// constraint = composer_store.key() == params.to,
93
+ /// constraint = composer_store.oft_store == params.from,
94
+ /// )]
95
+ /// pub composer_store: Account<'info, ComposerStore>,
96
+ /// ```
78
97
  #[proc_macro_attribute]
79
98
  pub fn composer_instruction(_attr: TokenStream, item: TokenStream) -> TokenStream {
80
99
  item
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layerzerolabs/oapp-solana-contracts",
3
- "version": "1.2.72",
3
+ "version": "1.2.74",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,14 +15,14 @@
15
15
  "rustfmt.toml"
16
16
  ],
17
17
  "dependencies": {
18
- "@layerzerolabs/framework-solana-anchor-trait": "1.2.72",
19
- "@layerzerolabs/rbac-solana-contracts": "1.2.72"
18
+ "@layerzerolabs/framework-solana-anchor-trait": "1.2.74",
19
+ "@layerzerolabs/rbac-solana-contracts": "1.2.74"
20
20
  },
21
21
  "devDependencies": {
22
- "@layerzerolabs/build-utils-rust": "1.2.72",
23
- "@layerzerolabs/tsup-configuration": "1.2.72",
24
- "@layerzerolabs/typescript-configuration": "1.2.72",
25
- "@layerzerolabs/vm-tooling-solana": "1.2.72"
22
+ "@layerzerolabs/build-utils-rust": "1.2.74",
23
+ "@layerzerolabs/tsup-configuration": "1.2.74",
24
+ "@layerzerolabs/typescript-configuration": "1.2.74",
25
+ "@layerzerolabs/vm-tooling-solana": "1.2.74"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "restricted",
@@ -1,3 +1,3 @@
1
1
  [toolchain]
2
- channel = "1.92.0"
2
+ channel = "1.97.1"
3
3
  components = ["rustfmt", "clippy"]
@@ -33,7 +33,6 @@ use crate::endpoint::{
33
33
  },
34
34
  };
35
35
  use anchor_lang::{
36
- error,
37
36
  prelude::{AccountInfo, CpiContext, ErrorCode, Key, Pubkey, Result},
38
37
  require, require_keys_eq, ToAccountInfos, ToAccountMetas,
39
38
  };
@@ -208,11 +207,22 @@ pub fn send(
208
207
  event_authority: accounts[8].clone(),
209
208
  program: accounts[9].clone(),
210
209
  };
211
- let rtn = endpoint::cpi::send(
210
+ invoke_send(
212
211
  make_cpi_ctx(accounts, cpi_accounts, SEND_MIN_ACCOUNTS_LEN).with_signer(&[seeds]),
213
212
  params,
214
- )?;
215
- Ok(rtn.get())
213
+ )
214
+ }
215
+
216
+ // SBPF v3 has fixed 4 KiB stack frames with no guard gaps, so a frame that overflows silently
217
+ // corrupts its neighbour instead of faulting. The generated CPI needs most of a frame on its own;
218
+ // kept out of line, neither it nor the caller exceeds 4 KiB (inlined, platform-tools v1.57 builds a
219
+ // 4.6 KiB frame).
220
+ #[inline(never)]
221
+ fn invoke_send<'a, 'b, 'c, 'info>(
222
+ ctx: CpiContext<'a, 'b, 'c, 'info, Send<'info>>,
223
+ params: SendParams,
224
+ ) -> Result<MessagingReceipt> {
225
+ Ok(endpoint::cpi::send(ctx, params)?.get())
216
226
  }
217
227
 
218
228
  /// Queries the Endpoint for the fee required to send a cross-chain message.
@@ -300,14 +310,24 @@ pub fn clear(
300
310
  event_authority: accounts[6].clone(),
301
311
  program: accounts[7].clone(),
302
312
  };
303
- let result = endpoint::cpi::clear(
313
+ invoke_clear(
304
314
  make_cpi_ctx(accounts, cpi_accounts, CLEAR_MIN_ACCOUNTS_LEN).with_signer(&[seeds]),
305
315
  params,
306
- )?;
307
- Ok(result.get())
316
+ )
317
+ }
318
+
319
+ /// Out of line for the same reason as [`invoke_send`].
320
+ #[inline(never)]
321
+ fn invoke_clear<'a, 'b, 'c, 'info>(
322
+ ctx: CpiContext<'a, 'b, 'c, 'info, Clear<'info>>,
323
+ params: ClearParams,
324
+ ) -> Result<[u8; 32]> {
325
+ Ok(endpoint::cpi::clear(ctx, params)?.get())
308
326
  }
309
327
 
310
- /// Skips the next inbound nonce on the Endpoint messaging channel.
328
+ /// Skips the next inbound nonce on the Endpoint messaging channel. The Endpoint only accepts
329
+ /// `inbound_nonce + 1`, the next unverified nonce, so this cannot reach a verified payload; use
330
+ /// [`burn`] or [`clear`] for one.
311
331
  ///
312
332
  /// # Accounts layout
313
333
  /// The `accounts` slice must follow the `Skip` struct field order:
@@ -353,7 +373,8 @@ pub fn skip(
353
373
  )
354
374
  }
355
375
 
356
- /// Permanently burns a verified payload hash so it can never be executed or re-verified.
376
+ /// Permanently burns a verified payload hash so it can never be executed or re-verified. The
377
+ /// Endpoint requires the payload's nonce to be at or below the inbound nonce.
357
378
  ///
358
379
  /// # Accounts layout
359
380
  /// The `accounts` slice must follow the `Burn` struct field order: