@layerzerolabs/oapp-solana-contracts 1.2.62 → 1.2.64
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 +1 -1
- package/Cargo.toml +2 -6
- package/README.md +15 -9
- package/macros/Cargo.toml +1 -1
- package/macros/src/instructions/composer/lz_compose_types_info.rs +2 -2
- package/macros/src/instructions/composer/lz_compose_types_v3.rs +18 -0
- package/macros/src/instructions/composer/mod.rs +2 -2
- package/macros/src/instructions/oapp/burn.rs +69 -0
- package/macros/src/instructions/oapp/clear.rs +70 -0
- package/macros/src/instructions/oapp/lz_receive_types_info.rs +1 -3
- package/macros/src/instructions/oapp/lz_receive_types_v3.rs +17 -0
- package/macros/src/instructions/oapp/mod.rs +10 -2
- package/macros/src/instructions/oapp/nilify.rs +69 -0
- package/macros/src/instructions/oapp/skip.rs +68 -0
- package/macros/src/lib.rs +2 -2
- package/macros/src/oapp.rs +1 -0
- package/package.json +9 -10
- package/src/common.rs +14 -96
- package/src/endpoint_cpi.rs +155 -13
- package/src/errors.rs +4 -3
- package/src/lib.rs +26 -12
- package/src/lz_compose_types_v3.rs +72 -0
- package/src/lz_plan.rs +71 -0
- package/src/{lz_receive_types_v2.rs → lz_receive_types_v3.rs} +27 -54
- package/src/oapp_info.rs +1 -1
- package/src/options.rs +5 -15
- package/src/types.rs +44 -0
- package/macros/src/instructions/composer/lz_compose_types_v2.rs +0 -17
- package/macros/src/instructions/oapp/lz_receive_types_v2.rs +0 -17
- package/src/lz_compose_types_v2.rs +0 -88
package/Anchor.toml
CHANGED
package/Cargo.toml
CHANGED
|
@@ -19,13 +19,9 @@ 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.
|
|
23
|
-
anchor-spl = { version = "1.
|
|
22
|
+
anchor-lang = { version = "1.1.2" }
|
|
23
|
+
anchor-spl = { version = "1.1.2" }
|
|
24
24
|
oapp-macros = { path = "macros" }
|
|
25
|
-
solana-address-lookup-table-interface = { version = "3.0.1", features = [
|
|
26
|
-
"bincode",
|
|
27
|
-
"bytemuck",
|
|
28
|
-
] }
|
|
29
25
|
solana-keccak-hasher = "3.1.0"
|
|
30
26
|
spl-type-length-value = { version = "0.9.1", features = ["derive"] }
|
|
31
27
|
spl-discriminator = "0.5.2"
|
package/README.md
CHANGED
|
@@ -65,8 +65,12 @@ Generated by the `#[oapp]` attribute macro from `oapp`.
|
|
|
65
65
|
| `next_nonce` | Yes | Yes | Read next inbound nonce |
|
|
66
66
|
| `is_compose_msg_sender` | Yes | Yes | Validate compose message sender |
|
|
67
67
|
| `lz_receive_types_info` | Yes | No | Return LzReceiveTypes version and accounts |
|
|
68
|
-
| `
|
|
68
|
+
| `lz_receive_types_v3` | No | No | Write the lz_receive execution plan to caller scratch |
|
|
69
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 |
|
|
70
74
|
|
|
71
75
|
### RBAC Instructions
|
|
72
76
|
|
|
@@ -85,6 +89,8 @@ Generated by the `#[rbac]` attribute macro from `rbac`. All have default impleme
|
|
|
85
89
|
>
|
|
86
90
|
> **Security Note (`lz_receive`):** The Endpoint does NOT validate the inbound peer. The `lz_receive` override MUST bind an `OAppPeer` PDA to `params.src_eid` via `seeds` and enforce `peer.address == params.sender` — recommended declaratively via Anchor's `constraint`. Omitting this check lets any program impersonate a registered peer. See the `#[oapp_instruction]` rustdoc for the canonical Anchor account snippet.
|
|
87
91
|
|
|
92
|
+
The program's role enum must implement `MessagingChannelRoles`. `clear`, `skip`, and `burn` use the messaging-channel manager role; `nilify` uses a separate message-nilifier role. The DefaultAdmin, as the OApp's Endpoint delegate, can already call these on the Endpoint directly; the roles let other keys do the same through the OApp. These wrappers omit a caller-controlled receiver and inject the OApp PDA into the Endpoint CPI.
|
|
93
|
+
|
|
88
94
|
### Initialization Requirements
|
|
89
95
|
|
|
90
96
|
The `#[oapp]` macro generates instruction entrypoints, but deployment initialization remains the program's responsibility. A production OApp `initialize` handler must complete these setup steps:
|
|
@@ -156,25 +162,25 @@ For the full `OAppInfo` struct, SDK decision flow, app-specific extensions, and
|
|
|
156
162
|
|
|
157
163
|
> LzReceiveTypes is an existing protocol that predates the OApp Standard. It is documented here for completeness, as it handles account discovery for `lz_receive` — the one instruction not covered by `OAppInfo`.
|
|
158
164
|
|
|
159
|
-
`lz_receive` is unique among OApp instructions: its accounts depend on the message content and cannot be resolved off-chain from a predefined template. The LzReceiveTypes protocol solves this by providing an on-chain instruction (`
|
|
165
|
+
`lz_receive` is unique among OApp instructions: its accounts depend on the message content and cannot be resolved off-chain from a predefined template. The LzReceiveTypes protocol solves this by providing an on-chain instruction (`lz_receive_types_v3`) that returns the exact accounts and instructions needed for a given message.
|
|
160
166
|
|
|
161
167
|
Key concepts:
|
|
162
168
|
|
|
163
|
-
- **
|
|
164
|
-
- **
|
|
165
|
-
- **`AddressLocator` enum** —
|
|
166
|
-
- **Multi-instruction support** — `
|
|
169
|
+
- **Simulated planning** — the Executor simulates `lz_receive_types_info` and then `lz_receive_types_v3`, which writes the plan into a caller-created scratch account, and submits the resulting instructions.
|
|
170
|
+
- **Top-level delivery** — planned instructions, including `lz_receive`, run as top-level instructions in the Executor's transaction, between its `PreExecute` and `PostExecute`, rather than through an Executor CPI, leaving `lz_receive` the full CPI depth (e.g. for ABA messaging).
|
|
171
|
+
- **`AddressLocator` enum** — accounts are referenced by literal address, the Executor payer, additional Executor-provided signers, or the Executor's execution-context account.
|
|
172
|
+
- **Multi-instruction support** — `lz_receive_types_v3` can return multiple instructions (preprocessing steps + `lz_receive`), executed atomically in a single transaction.
|
|
167
173
|
- **Versioned via `lz_receive_types_info`** — the protocol self-describes its version; the Executor reads this to determine how to interact with the OApp.
|
|
168
174
|
|
|
169
|
-
For the
|
|
175
|
+
For the planning flow, scratch sizing, and plan format, see [`lz-receive-types.md`](./docs/lz-receive-types.md).
|
|
170
176
|
|
|
171
177
|
---
|
|
172
178
|
|
|
173
179
|
## Appendix: LzComposeTypes
|
|
174
180
|
|
|
175
181
|
`lz_compose` is the follow-up execution phase for composed messages emitted by
|
|
176
|
-
`lz_receive`. LzComposeTypes uses the same
|
|
177
|
-
|
|
182
|
+
`lz_receive`. LzComposeTypes uses the same V3 planning protocol and plan encoding
|
|
183
|
+
as LzReceiveTypes, but its interface is scoped to composer programs and
|
|
178
184
|
`LzComposeParams`.
|
|
179
185
|
|
|
180
186
|
For the compose-specific interface and differences, see
|
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.
|
|
14
|
+
anchor-lang = { version = "1.1.2" }
|
|
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"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
//! The framework does not enforce it at compile time, so a mismatch only
|
|
13
13
|
//! surfaces as a runtime failure when the Executor calls the deployed program.
|
|
14
14
|
//!
|
|
15
|
-
//! This follows the same
|
|
15
|
+
//! This follows the same V3 account-discovery model as `lz_receive_types_info`.
|
|
16
16
|
//! See `docs/lz-compose-types.md` for the compose-specific differences.
|
|
17
17
|
|
|
18
18
|
use super::ComposerCodegenContext;
|
|
@@ -22,7 +22,7 @@ use quote::quote;
|
|
|
22
22
|
pub(super) fn spec() -> InstructionSpec<ComposerCodegenContext> {
|
|
23
23
|
InstructionSpec {
|
|
24
24
|
params_type: Some(quote!(::oapp::types::LzComposeParams)),
|
|
25
|
-
return_type: quote!((u8, ::oapp::
|
|
25
|
+
return_type: quote!((u8, ::oapp::lz_compose_types_v3::LzComposeTypesV3Accounts)),
|
|
26
26
|
is_view: true,
|
|
27
27
|
default_impl: None,
|
|
28
28
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//! Code generator for the `lz_compose_types_v3` instruction.
|
|
2
|
+
//!
|
|
3
|
+
//! Required override (no default). Users MUST provide a custom handler named
|
|
4
|
+
//! `lz_compose_types_v3` with `#[composer_instruction]`. The handler writes its plan with
|
|
5
|
+
//! `oapp::lz_plan::write` and returns the plan's encoded length; see `docs/lz-compose-types.md`.
|
|
6
|
+
|
|
7
|
+
use super::ComposerCodegenContext;
|
|
8
|
+
use anchor_trait::InstructionSpec;
|
|
9
|
+
use quote::quote;
|
|
10
|
+
|
|
11
|
+
pub(super) fn spec() -> InstructionSpec<ComposerCodegenContext> {
|
|
12
|
+
InstructionSpec {
|
|
13
|
+
params_type: Some(quote!(::oapp::types::LzComposeParams)),
|
|
14
|
+
return_type: quote!(u32),
|
|
15
|
+
is_view: false,
|
|
16
|
+
default_impl: None,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
mod lz_compose;
|
|
7
7
|
mod lz_compose_types_info;
|
|
8
|
-
mod
|
|
8
|
+
mod lz_compose_types_v3;
|
|
9
9
|
|
|
10
10
|
use anchor_trait::declare_instructions;
|
|
11
11
|
|
|
@@ -18,6 +18,6 @@ declare_instructions! {
|
|
|
18
18
|
context = ComposerCodegenContext;
|
|
19
19
|
|
|
20
20
|
LzComposeTypesInfo => lz_compose_types_info,
|
|
21
|
-
|
|
21
|
+
LzComposeTypesV3 => lz_compose_types_v3,
|
|
22
22
|
LzCompose => lz_compose,
|
|
23
23
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//! Code generator for the messaging-channel `burn` instruction.
|
|
2
|
+
//!
|
|
3
|
+
//! Permanently disables execution / re-verification of a payload.
|
|
4
|
+
//! Requires [`MessagingChannelRoles::messaging_channel_manager_role`]. The Endpoint accounts are
|
|
5
|
+
//! passed as remaining accounts in `oapp::endpoint_cpi::burn` order.
|
|
6
|
+
|
|
7
|
+
use super::CodegenContext;
|
|
8
|
+
use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
|
|
9
|
+
use quote::{format_ident, quote};
|
|
10
|
+
use syn::parse_quote;
|
|
11
|
+
|
|
12
|
+
pub(super) fn spec() -> InstructionSpec<CodegenContext> {
|
|
13
|
+
InstructionSpec {
|
|
14
|
+
params_type: Some(quote!(::oapp::types::BurnParams)),
|
|
15
|
+
return_type: quote!(()),
|
|
16
|
+
is_view: false,
|
|
17
|
+
default_impl: Some(DefaultImpl {
|
|
18
|
+
handler_ident: format_ident!("apply"),
|
|
19
|
+
generator: generate_default_impl,
|
|
20
|
+
}),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn generate_default_impl(
|
|
25
|
+
ctx: &CodegenContext,
|
|
26
|
+
spec: &InstructionSpec<CodegenContext>,
|
|
27
|
+
) -> DefaultAccounts {
|
|
28
|
+
let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
|
|
29
|
+
let params_type = spec.params_type.as_ref().unwrap();
|
|
30
|
+
let return_type = &spec.return_type;
|
|
31
|
+
let oapp_type = &ctx.oapp_type;
|
|
32
|
+
let role_type = &ctx.role_type;
|
|
33
|
+
|
|
34
|
+
DefaultAccounts {
|
|
35
|
+
struct_type: parse_quote! {
|
|
36
|
+
#[::rbac::only_role(
|
|
37
|
+
role = #role_type::messaging_channel_manager_role(),
|
|
38
|
+
state = oapp,
|
|
39
|
+
authority = authority
|
|
40
|
+
)]
|
|
41
|
+
#[derive(Accounts)]
|
|
42
|
+
pub struct StdBurn<'info> {
|
|
43
|
+
pub authority: Signer<'info>,
|
|
44
|
+
|
|
45
|
+
pub oapp: Account<'info, #oapp_type>,
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
impl_block: parse_quote! {
|
|
49
|
+
impl StdBurn<'_> {
|
|
50
|
+
pub fn #handler_ident(ctx: &mut Context<Self>, params: &#params_type) -> Result<#return_type> {
|
|
51
|
+
let receiver = ctx.accounts.oapp.key();
|
|
52
|
+
::oapp::endpoint_cpi::burn(
|
|
53
|
+
::oapp::endpoint::ID,
|
|
54
|
+
receiver,
|
|
55
|
+
ctx.remaining_accounts,
|
|
56
|
+
&ctx.accounts.oapp.signer_seeds(),
|
|
57
|
+
::oapp::endpoint::types::BurnParams {
|
|
58
|
+
receiver,
|
|
59
|
+
src_eid: params.src_eid,
|
|
60
|
+
sender: params.sender,
|
|
61
|
+
nonce: params.nonce,
|
|
62
|
+
payload_hash: params.payload_hash,
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//! Code generator for the messaging-channel `clear` instruction.
|
|
2
|
+
//!
|
|
3
|
+
//! Consumes a verified inbound message without running the normal receive
|
|
4
|
+
//! callback. Requires [`MessagingChannelRoles::messaging_channel_manager_role`]. The Endpoint
|
|
5
|
+
//! accounts are passed as remaining accounts in `oapp::endpoint_cpi::clear` order.
|
|
6
|
+
|
|
7
|
+
use super::CodegenContext;
|
|
8
|
+
use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
|
|
9
|
+
use quote::{format_ident, quote};
|
|
10
|
+
use syn::parse_quote;
|
|
11
|
+
|
|
12
|
+
pub(super) fn spec() -> InstructionSpec<CodegenContext> {
|
|
13
|
+
InstructionSpec {
|
|
14
|
+
params_type: Some(quote!(::oapp::types::ClearParams)),
|
|
15
|
+
return_type: quote!([u8; 32]),
|
|
16
|
+
is_view: false,
|
|
17
|
+
default_impl: Some(DefaultImpl {
|
|
18
|
+
handler_ident: format_ident!("apply"),
|
|
19
|
+
generator: generate_default_impl,
|
|
20
|
+
}),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn generate_default_impl(
|
|
25
|
+
ctx: &CodegenContext,
|
|
26
|
+
spec: &InstructionSpec<CodegenContext>,
|
|
27
|
+
) -> DefaultAccounts {
|
|
28
|
+
let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
|
|
29
|
+
let params_type = spec.params_type.as_ref().unwrap();
|
|
30
|
+
let return_type = &spec.return_type;
|
|
31
|
+
let oapp_type = &ctx.oapp_type;
|
|
32
|
+
let role_type = &ctx.role_type;
|
|
33
|
+
|
|
34
|
+
DefaultAccounts {
|
|
35
|
+
struct_type: parse_quote! {
|
|
36
|
+
#[::rbac::only_role(
|
|
37
|
+
role = #role_type::messaging_channel_manager_role(),
|
|
38
|
+
state = oapp,
|
|
39
|
+
authority = authority
|
|
40
|
+
)]
|
|
41
|
+
#[derive(Accounts)]
|
|
42
|
+
pub struct StdClear<'info> {
|
|
43
|
+
pub authority: Signer<'info>,
|
|
44
|
+
|
|
45
|
+
pub oapp: Account<'info, #oapp_type>,
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
impl_block: parse_quote! {
|
|
49
|
+
impl StdClear<'_> {
|
|
50
|
+
pub fn #handler_ident(ctx: &mut Context<Self>, params: &#params_type) -> Result<#return_type> {
|
|
51
|
+
let receiver = ctx.accounts.oapp.key();
|
|
52
|
+
::oapp::endpoint_cpi::clear(
|
|
53
|
+
::oapp::endpoint::ID,
|
|
54
|
+
receiver,
|
|
55
|
+
ctx.remaining_accounts,
|
|
56
|
+
&ctx.accounts.oapp.signer_seeds(),
|
|
57
|
+
::oapp::endpoint::types::ClearParams {
|
|
58
|
+
receiver,
|
|
59
|
+
src_eid: params.src_eid,
|
|
60
|
+
sender: params.sender,
|
|
61
|
+
nonce: params.nonce,
|
|
62
|
+
guid: params.guid,
|
|
63
|
+
message: params.message.clone(),
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
//! Custom handlers MUST declare an `Accounts` struct matching this shape.
|
|
12
12
|
//! The framework does not enforce it at compile time, so a mismatch only
|
|
13
13
|
//! surfaces as a runtime failure when the Executor calls the deployed program.
|
|
14
|
-
//!
|
|
15
|
-
//! See: <https://docs.layerzero.network/v2/developers/solana/oapp/overview#how-lz_receive_types_v2-works>
|
|
16
14
|
|
|
17
15
|
use super::CodegenContext;
|
|
18
16
|
use anchor_trait::InstructionSpec;
|
|
@@ -21,7 +19,7 @@ use quote::quote;
|
|
|
21
19
|
pub(super) fn spec() -> InstructionSpec<CodegenContext> {
|
|
22
20
|
InstructionSpec {
|
|
23
21
|
params_type: Some(quote!(::oapp::types::LzReceiveParams)),
|
|
24
|
-
return_type: quote!((u8, ::oapp::
|
|
22
|
+
return_type: quote!((u8, ::oapp::lz_receive_types_v3::LzReceiveTypesV3Accounts)),
|
|
25
23
|
is_view: true,
|
|
26
24
|
default_impl: None,
|
|
27
25
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//! Code generator for the `lz_receive_types_v3` instruction.
|
|
2
|
+
//!
|
|
3
|
+
//! Required override (no default). The handler writes its plan with `oapp::lz_plan::write` and
|
|
4
|
+
//! returns the plan's encoded length; see `docs/lz-receive-types.md`.
|
|
5
|
+
|
|
6
|
+
use super::CodegenContext;
|
|
7
|
+
use anchor_trait::InstructionSpec;
|
|
8
|
+
use quote::quote;
|
|
9
|
+
|
|
10
|
+
pub(super) fn spec() -> InstructionSpec<CodegenContext> {
|
|
11
|
+
InstructionSpec {
|
|
12
|
+
params_type: Some(quote!(::oapp::types::LzReceiveParams)),
|
|
13
|
+
return_type: quote!(u32),
|
|
14
|
+
is_view: false,
|
|
15
|
+
default_impl: None,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -4,16 +4,20 @@
|
|
|
4
4
|
//! `InstructionName::spec()` maps instruction variants to their specs.
|
|
5
5
|
|
|
6
6
|
pub(crate) mod accept_default_admin_transfer;
|
|
7
|
+
mod burn;
|
|
8
|
+
mod clear;
|
|
7
9
|
mod get_enforced_options;
|
|
8
10
|
mod get_peer;
|
|
9
11
|
mod init_enforced_options;
|
|
10
12
|
mod is_compose_msg_sender;
|
|
11
13
|
mod lz_receive;
|
|
12
14
|
mod lz_receive_types_info;
|
|
13
|
-
mod
|
|
15
|
+
mod lz_receive_types_v3;
|
|
14
16
|
mod next_nonce;
|
|
17
|
+
mod nilify;
|
|
15
18
|
mod set_enforced_options;
|
|
16
19
|
mod set_peer;
|
|
20
|
+
mod skip;
|
|
17
21
|
|
|
18
22
|
use anchor_trait::declare_instructions;
|
|
19
23
|
use proc_macro2::TokenStream;
|
|
@@ -36,6 +40,10 @@ declare_instructions! {
|
|
|
36
40
|
NextNonce => next_nonce,
|
|
37
41
|
IsComposeMsgSender => is_compose_msg_sender,
|
|
38
42
|
LzReceiveTypesInfo => lz_receive_types_info,
|
|
39
|
-
|
|
43
|
+
LzReceiveTypesV3 => lz_receive_types_v3,
|
|
40
44
|
LzReceive => lz_receive,
|
|
45
|
+
Clear => clear,
|
|
46
|
+
Skip => skip,
|
|
47
|
+
Burn => burn,
|
|
48
|
+
Nilify => nilify,
|
|
41
49
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//! Code generator for the messaging-channel `nilify` instruction.
|
|
2
|
+
//!
|
|
3
|
+
//! Temporarily blocks execution until re-verification.
|
|
4
|
+
//! Requires [`MessagingChannelRoles::message_nilifier_role`]. The Endpoint accounts are passed as
|
|
5
|
+
//! remaining accounts in `oapp::endpoint_cpi::nilify` order.
|
|
6
|
+
|
|
7
|
+
use super::CodegenContext;
|
|
8
|
+
use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
|
|
9
|
+
use quote::{format_ident, quote};
|
|
10
|
+
use syn::parse_quote;
|
|
11
|
+
|
|
12
|
+
pub(super) fn spec() -> InstructionSpec<CodegenContext> {
|
|
13
|
+
InstructionSpec {
|
|
14
|
+
params_type: Some(quote!(::oapp::types::NilifyParams)),
|
|
15
|
+
return_type: quote!(()),
|
|
16
|
+
is_view: false,
|
|
17
|
+
default_impl: Some(DefaultImpl {
|
|
18
|
+
handler_ident: format_ident!("apply"),
|
|
19
|
+
generator: generate_default_impl,
|
|
20
|
+
}),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn generate_default_impl(
|
|
25
|
+
ctx: &CodegenContext,
|
|
26
|
+
spec: &InstructionSpec<CodegenContext>,
|
|
27
|
+
) -> DefaultAccounts {
|
|
28
|
+
let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
|
|
29
|
+
let params_type = spec.params_type.as_ref().unwrap();
|
|
30
|
+
let return_type = &spec.return_type;
|
|
31
|
+
let oapp_type = &ctx.oapp_type;
|
|
32
|
+
let role_type = &ctx.role_type;
|
|
33
|
+
|
|
34
|
+
DefaultAccounts {
|
|
35
|
+
struct_type: parse_quote! {
|
|
36
|
+
#[::rbac::only_role(
|
|
37
|
+
role = #role_type::message_nilifier_role(),
|
|
38
|
+
state = oapp,
|
|
39
|
+
authority = authority
|
|
40
|
+
)]
|
|
41
|
+
#[derive(Accounts)]
|
|
42
|
+
pub struct StdNilify<'info> {
|
|
43
|
+
pub authority: Signer<'info>,
|
|
44
|
+
|
|
45
|
+
pub oapp: Account<'info, #oapp_type>,
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
impl_block: parse_quote! {
|
|
49
|
+
impl StdNilify<'_> {
|
|
50
|
+
pub fn #handler_ident(ctx: &mut Context<Self>, params: &#params_type) -> Result<#return_type> {
|
|
51
|
+
let receiver = ctx.accounts.oapp.key();
|
|
52
|
+
::oapp::endpoint_cpi::nilify(
|
|
53
|
+
::oapp::endpoint::ID,
|
|
54
|
+
receiver,
|
|
55
|
+
ctx.remaining_accounts,
|
|
56
|
+
&ctx.accounts.oapp.signer_seeds(),
|
|
57
|
+
::oapp::endpoint::types::NilifyParams {
|
|
58
|
+
receiver,
|
|
59
|
+
src_eid: params.src_eid,
|
|
60
|
+
sender: params.sender,
|
|
61
|
+
nonce: params.nonce,
|
|
62
|
+
payload_hash: params.payload_hash,
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//! Code generator for the messaging-channel `skip` instruction.
|
|
2
|
+
//!
|
|
3
|
+
//! Skips the next inbound nonce. Requires
|
|
4
|
+
//! [`MessagingChannelRoles::messaging_channel_manager_role`]. The Endpoint accounts are passed as
|
|
5
|
+
//! remaining accounts in `oapp::endpoint_cpi::skip` order.
|
|
6
|
+
|
|
7
|
+
use super::CodegenContext;
|
|
8
|
+
use anchor_trait::{DefaultAccounts, DefaultImpl, InstructionSpec};
|
|
9
|
+
use quote::{format_ident, quote};
|
|
10
|
+
use syn::parse_quote;
|
|
11
|
+
|
|
12
|
+
pub(super) fn spec() -> InstructionSpec<CodegenContext> {
|
|
13
|
+
InstructionSpec {
|
|
14
|
+
params_type: Some(quote!(::oapp::types::SkipParams)),
|
|
15
|
+
return_type: quote!(()),
|
|
16
|
+
is_view: false,
|
|
17
|
+
default_impl: Some(DefaultImpl {
|
|
18
|
+
handler_ident: format_ident!("apply"),
|
|
19
|
+
generator: generate_default_impl,
|
|
20
|
+
}),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn generate_default_impl(
|
|
25
|
+
ctx: &CodegenContext,
|
|
26
|
+
spec: &InstructionSpec<CodegenContext>,
|
|
27
|
+
) -> DefaultAccounts {
|
|
28
|
+
let handler_ident = &spec.default_impl.as_ref().unwrap().handler_ident;
|
|
29
|
+
let params_type = spec.params_type.as_ref().unwrap();
|
|
30
|
+
let return_type = &spec.return_type;
|
|
31
|
+
let oapp_type = &ctx.oapp_type;
|
|
32
|
+
let role_type = &ctx.role_type;
|
|
33
|
+
|
|
34
|
+
DefaultAccounts {
|
|
35
|
+
struct_type: parse_quote! {
|
|
36
|
+
#[::rbac::only_role(
|
|
37
|
+
role = #role_type::messaging_channel_manager_role(),
|
|
38
|
+
state = oapp,
|
|
39
|
+
authority = authority
|
|
40
|
+
)]
|
|
41
|
+
#[derive(Accounts)]
|
|
42
|
+
pub struct StdSkip<'info> {
|
|
43
|
+
pub authority: Signer<'info>,
|
|
44
|
+
|
|
45
|
+
pub oapp: Account<'info, #oapp_type>,
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
impl_block: parse_quote! {
|
|
49
|
+
impl StdSkip<'_> {
|
|
50
|
+
pub fn #handler_ident(ctx: &mut Context<Self>, params: &#params_type) -> Result<#return_type> {
|
|
51
|
+
let receiver = ctx.accounts.oapp.key();
|
|
52
|
+
::oapp::endpoint_cpi::skip(
|
|
53
|
+
::oapp::endpoint::ID,
|
|
54
|
+
receiver,
|
|
55
|
+
ctx.remaining_accounts,
|
|
56
|
+
&ctx.accounts.oapp.signer_seeds(),
|
|
57
|
+
::oapp::endpoint::types::SkipParams {
|
|
58
|
+
receiver,
|
|
59
|
+
src_eid: params.src_eid,
|
|
60
|
+
sender: params.sender,
|
|
61
|
+
nonce: params.nonce,
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
}
|
package/macros/src/lib.rs
CHANGED
|
@@ -53,7 +53,7 @@ pub fn oapp_instruction(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|
|
53
53
|
|
|
54
54
|
/// Attribute macro for generating Composer program entrypoints.
|
|
55
55
|
///
|
|
56
|
-
/// This macro generates `lz_compose`, `
|
|
56
|
+
/// This macro generates `lz_compose`, `lz_compose_types_v3`, and
|
|
57
57
|
/// `lz_compose_types_info` instruction entrypoints for programs that implement
|
|
58
58
|
/// the LayerZero composer interface. All three instructions are required —
|
|
59
59
|
/// the implementor must provide custom handlers for each via
|
|
@@ -68,7 +68,7 @@ pub fn composer(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|
|
68
68
|
|
|
69
69
|
/// Marker attribute for required Composer instruction handlers.
|
|
70
70
|
///
|
|
71
|
-
/// All three instructions (`lz_compose`, `
|
|
71
|
+
/// All three instructions (`lz_compose`, `lz_compose_types_v3`, `lz_compose_types_info`)
|
|
72
72
|
/// must be provided — there are no framework-supplied defaults. Each handler's
|
|
73
73
|
/// `ctx` parameter must be taken **by reference** (`&Context<T>`).
|
|
74
74
|
///
|
package/macros/src/oapp.rs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layerzerolabs/oapp-solana-contracts",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.64",
|
|
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/
|
|
19
|
-
"@layerzerolabs/
|
|
18
|
+
"@layerzerolabs/framework-solana-anchor-trait": "1.2.64",
|
|
19
|
+
"@layerzerolabs/rbac-solana-contracts": "1.2.64"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@layerzerolabs/tsup-configuration": "1.2.
|
|
23
|
-
"@layerzerolabs/build-utils-rust": "1.2.
|
|
24
|
-
"@layerzerolabs/
|
|
25
|
-
"@layerzerolabs/
|
|
22
|
+
"@layerzerolabs/tsup-configuration": "1.2.64",
|
|
23
|
+
"@layerzerolabs/build-utils-rust": "1.2.64",
|
|
24
|
+
"@layerzerolabs/typescript-configuration": "1.2.64",
|
|
25
|
+
"@layerzerolabs/vm-tooling-solana": "1.2.64"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "restricted",
|
|
@@ -30,13 +30,12 @@
|
|
|
30
30
|
},
|
|
31
31
|
"externalRepoConfig": {
|
|
32
32
|
"targets": [
|
|
33
|
-
"audit-external"
|
|
34
|
-
"console-solana-v1-internal"
|
|
33
|
+
"audit-external"
|
|
35
34
|
]
|
|
36
35
|
},
|
|
37
36
|
"implicitDependencies": {
|
|
38
37
|
"@layerzerolabs/framework-solana-anchor-trait": "workspace:*",
|
|
39
|
-
"@layerzerolabs/
|
|
38
|
+
"@layerzerolabs/rbac-solana-contracts": "workspace:*"
|
|
40
39
|
},
|
|
41
40
|
"scripts": {
|
|
42
41
|
"allow-read-write": "[ -z \"$CI\" ] || sudo chmod -R a+rwx ./target",
|