-
Notifications
You must be signed in to change notification settings - Fork 3
add skill for Pinocchio framework #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||||||||||||||||||||||||
| # Delegation Patterns (Rust Programs) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Rust Program Setup | ||||||||||||||||||||||||||||||||
| ## Anchor Framework | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Dependencies | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
@@ -30,7 +30,7 @@ pub mod my_program { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Delegate Instruction | ||||||||||||||||||||||||||||||||
| ### Delegate Instruction | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub fn delegate(ctx: Context<DelegateInput>, uid: String) -> Result<()> { | ||||||||||||||||||||||||||||||||
|
|
@@ -55,7 +55,7 @@ pub struct DelegateInput<'info> { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Undelegate Instruction | ||||||||||||||||||||||||||||||||
| ### Undelegate Instruction | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub fn undelegate(ctx: Context<Undelegate>) -> Result<()> { | ||||||||||||||||||||||||||||||||
|
|
@@ -78,7 +78,7 @@ pub struct Undelegate<'info> { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Commit Without Undelegating | ||||||||||||||||||||||||||||||||
| ### Commit Without Undelegating | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub fn commit(ctx: Context<CommitState>) -> Result<()> { | ||||||||||||||||||||||||||||||||
|
|
@@ -92,16 +92,166 @@ pub fn commit(ctx: Context<CommitState>) -> Result<()> { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Common Gotchas | ||||||||||||||||||||||||||||||||
| ### Anchor Gotchas | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Method Name Convention | ||||||||||||||||||||||||||||||||
| #### Method Name Convention | ||||||||||||||||||||||||||||||||
| The delegate method is auto-generated as `delegate_<field_name>`: | ||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub my_account: AccountInfo<'info>, // => ctx.accounts.delegate_my_account() | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Don't use `Account<>` in delegate context | ||||||||||||||||||||||||||||||||
| Use `AccountInfo` with `del` constraint instead. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Don't skip the `#[commit]` macro | ||||||||||||||||||||||||||||||||
| Required for undelegate context. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ## Pinocchio Framework | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Dependencies | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```toml | ||||||||||||||||||||||||||||||||
| # Cargo.toml | ||||||||||||||||||||||||||||||||
| [dependencies] | ||||||||||||||||||||||||||||||||
| pinocchio = { version = "0.10.2", features = ["cpi", "copy"] } | ||||||||||||||||||||||||||||||||
| pinocchio-log = { version = "0.5" } | ||||||||||||||||||||||||||||||||
| pinocchio-system = { version = "0.5" } | ||||||||||||||||||||||||||||||||
| ephemeral-rollups-pinocchio = { version = "0.8.5" } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
Comment on lines
+113
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: As of February 7, 2026, the latest 🌐 Web query:
💡 Result: Latest published crate versions (per docs.rs “latest” / crate page):
Sources: [1] pinocchio-log docs.rs, [2] pinocchio-system docs.rs, [3] ephemeral-rollups-pinocchio docs.rs. 🌐 Web query:
💡 Result: As of February 7, 2026, I don’t see a In the current docs for
What is deprecated is the Sources: [1] [2] [3] Update Cargo.toml to use valid published versions.
The [dependencies]
pinocchio = { version = "0.10.1", features = ["cpi", "copy"] }
pinocchio-log = { version = "0.5.1" }
pinocchio-system = { version = "0.5" }
ephemeral-rollups-pinocchio = { version = "0.8.4" }🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Imports | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| use ephemeral_rollups_pinocchio::instruction::delegate_account; | ||||||||||||||||||||||||||||||||
| use ephemeral_rollups_pinocchio::instruction::{ | ||||||||||||||||||||||||||||||||
| commit_accounts, commit_and_undelegate_accounts, undelegate, | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| use ephemeral_rollups_pinocchio::types::DelegateConfig; | ||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Program Setup | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| No macros needed. Pinocchio uses explicit account slicing and manual instruction dispatch instead of Anchor's `#[program]`/`#[ephemeral]` macros. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Delegate Instruction | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub fn process_delegate( | ||||||||||||||||||||||||||||||||
| _program_id: &Address, | ||||||||||||||||||||||||||||||||
| accounts: &[AccountView], | ||||||||||||||||||||||||||||||||
| bump: u8, | ||||||||||||||||||||||||||||||||
| ) -> ProgramResult { | ||||||||||||||||||||||||||||||||
| let [payer, pda_to_delegate, owner_program, delegation_buffer, | ||||||||||||||||||||||||||||||||
| delegation_record, delegation_metadata, _delegation_program, | ||||||||||||||||||||||||||||||||
| system_program, rest @ ..] = accounts | ||||||||||||||||||||||||||||||||
| else { | ||||||||||||||||||||||||||||||||
| return Err(ProgramError::NotEnoughAccountKeys); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| let validator = rest.first().map(|account| *account.address()); | ||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Document when the optional validator account should be provided. The code extracts an optional 📖 Suggested documentation additionAdd a comment above line 150: } else {
return Err(ProgramError::NotEnoughAccountKeys);
};
+ // Optional: provide a validator account to enforce validation on the ER
let validator = rest.first().map(|account| *account.address());🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| let seeds: &[&[u8]] = &[b"seed", payer.address().as_ref()]; | ||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Seeds differ between Anchor and Pinocchio examples - clarify the pattern. The Anchor example uses 💡 Suggested clarification+ // Seeds for PDA derivation (adjust based on your program's needs)
+ // Example: using payer address as seed component
let seeds: &[&[u8]] = &[b"seed", payer.address().as_ref()];📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| delegate_account( | ||||||||||||||||||||||||||||||||
| &[ | ||||||||||||||||||||||||||||||||
| payer, | ||||||||||||||||||||||||||||||||
| pda_to_delegate, | ||||||||||||||||||||||||||||||||
| owner_program, | ||||||||||||||||||||||||||||||||
| delegation_buffer, | ||||||||||||||||||||||||||||||||
| delegation_record, | ||||||||||||||||||||||||||||||||
| delegation_metadata, | ||||||||||||||||||||||||||||||||
| system_program, | ||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||
| seeds, | ||||||||||||||||||||||||||||||||
| bump, | ||||||||||||||||||||||||||||||||
| DelegateConfig { | ||||||||||||||||||||||||||||||||
| validator, | ||||||||||||||||||||||||||||||||
| ..Default::default() | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Undelegate Instruction | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub fn process_undelegate( | ||||||||||||||||||||||||||||||||
| _program_id: &Address, | ||||||||||||||||||||||||||||||||
| accounts: &[AccountView], | ||||||||||||||||||||||||||||||||
| ) -> ProgramResult { | ||||||||||||||||||||||||||||||||
| let [payer, my_account, magic_program, magic_context] = accounts else { | ||||||||||||||||||||||||||||||||
| return Err(ProgramError::NotEnoughAccountKeys); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if !payer.is_signer() { | ||||||||||||||||||||||||||||||||
| return Err(ProgramError::MissingRequiredSignature); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| commit_and_undelegate_accounts( | ||||||||||||||||||||||||||||||||
| payer, | ||||||||||||||||||||||||||||||||
| &[*my_account], | ||||||||||||||||||||||||||||||||
| magic_context, | ||||||||||||||||||||||||||||||||
| magic_program, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // REQUIRED: Handle the undelegation callback from the delegation program | ||||||||||||||||||||||||||||||||
| pub fn process_undelegation_callback( | ||||||||||||||||||||||||||||||||
| program_id: &Address, | ||||||||||||||||||||||||||||||||
| accounts: &[AccountView], | ||||||||||||||||||||||||||||||||
| ix_data: &[u8], | ||||||||||||||||||||||||||||||||
| ) -> ProgramResult { | ||||||||||||||||||||||||||||||||
| let [delegated_acc, buffer_acc, payer, _system_program, ..] = accounts else { | ||||||||||||||||||||||||||||||||
| return Err(ProgramError::NotEnoughAccountKeys); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| undelegate(delegated_acc, program_id, buffer_acc, payer, ix_data)?; | ||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Commit Without Undelegating | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| pub fn process_commit( | ||||||||||||||||||||||||||||||||
| _program_id: &Address, | ||||||||||||||||||||||||||||||||
| accounts: &[AccountView], | ||||||||||||||||||||||||||||||||
| ) -> ProgramResult { | ||||||||||||||||||||||||||||||||
| let [payer, my_account, magic_program, magic_context] = accounts else { | ||||||||||||||||||||||||||||||||
| return Err(ProgramError::NotEnoughAccountKeys); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if !payer.is_signer() { | ||||||||||||||||||||||||||||||||
| return Err(ProgramError::MissingRequiredSignature); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| commit_accounts( | ||||||||||||||||||||||||||||||||
| payer, | ||||||||||||||||||||||||||||||||
| &[*my_account], | ||||||||||||||||||||||||||||||||
| magic_context, | ||||||||||||||||||||||||||||||||
| magic_program, | ||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Pinocchio Gotchas | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Undelegation Callback Required | ||||||||||||||||||||||||||||||||
| You must implement a `process_undelegation_callback` handler that calls `undelegate()` — the delegation program invokes this on your program when undelegating. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #### Copy Semantics for Account References | ||||||||||||||||||||||||||||||||
| `commit_accounts` and `commit_and_undelegate_accounts` take `&[AccountView]` (copied), not references like Anchor's `&AccountInfo`. This requires the `copy` feature on the `pinocchio` crate. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+241
to
+248
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the same callback name as the example ( ✏️ Suggested wording fix-You must implement a `process_undelegation_callback` handler that calls `undelegate()` — the delegation program invokes this on your program when undelegating.
+You must implement an `undelegation_callback` handler that calls `undelegate()` — the delegation program invokes this on your program when undelegating.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| ## Common Gotchas | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### PDA Seeds Must Match | ||||||||||||||||||||||||||||||||
| Seeds in delegate instruction must exactly match account definition: | ||||||||||||||||||||||||||||||||
| Seeds in delegate instruction must exactly match account definition. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| **Anchor:** | ||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| #[account(mut, del, seeds = [b"tomo", uid.as_bytes()], bump)] | ||||||||||||||||||||||||||||||||
| pub tomo: AccountInfo<'info>, | ||||||||||||||||||||||||||||||||
|
|
@@ -110,6 +260,15 @@ pub tomo: AccountInfo<'info>, | |||||||||||||||||||||||||||||||
| ctx.accounts.delegate_tomo(&payer, &[b"tomo", uid.as_bytes()], config)?; | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| **Pinocchio:** | ||||||||||||||||||||||||||||||||
| ```rust | ||||||||||||||||||||||||||||||||
| // Seeds used to derive the PDA | ||||||||||||||||||||||||||||||||
| let seeds: &[&[u8]] = &[b"seed", payer.address().as_ref()]; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // delegate_account call - seeds must match the PDA derivation | ||||||||||||||||||||||||||||||||
| delegate_account(&[...], seeds, bump, delegate_config)?; | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ### Account Owner Changes on Delegation | ||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||
| Not delegated: account.owner == YOUR_PROGRAM_ID | ||||||||||||||||||||||||||||||||
|
|
@@ -128,6 +287,4 @@ Delegated: account.owner == DELEGATION_PROGRAM_ID | |||||||||||||||||||||||||||||||
| ### Don'ts | ||||||||||||||||||||||||||||||||
| - Don't send delegate tx to ER - Delegation always goes to base layer | ||||||||||||||||||||||||||||||||
| - Don't send operations to base layer - Delegated account ops go to ER | ||||||||||||||||||||||||||||||||
| - Don't forget the `#[ephemeral]` macro - Required on program module | ||||||||||||||||||||||||||||||||
| - Don't use `Account<>` in delegate context - Use `AccountInfo` with `del` constraint | ||||||||||||||||||||||||||||||||
| - Don't skip the `#[commit]` macro - Required for undelegate context | ||||||||||||||||||||||||||||||||
| - Don't forget the `#[ephemeral]` macro - Required on program module (Anchor) | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Add blank lines around headings and code fences for markdown compliance.
The markdown linter flags missing blank lines around several headings (lines 97, 103, 106) and a code fence (line 99). While this doesn't affect rendering in most viewers, it's good practice to follow markdown conventions for consistency across the documentation.
📝 Suggested formatting fixes
Don't use
Account<>in delegate contextUse
AccountInfowithdelconstraint instead.Don't skip the
#[commit]macroRequired for undelegate context.
In
@skill/delegation.mdaround lines 97 - 108, Add blank lines before and afterthe "Method Name Convention" heading, the Rust code fence that shows the
delegate example (pub my_account: AccountInfo<'info>, // =>
ctx.accounts.delegate_my_account()), and before the "Don't use
Account<>indelegate context" and "Don't skip the
#[commit]macro" headings so themarkdown linter stops flagging missing surrounding blank lines; ensure there is
an empty line above and below each heading and the fenced code block to comply
with Markdown conventions.