Add Token-2022 cpi-guard Pinocchio example - #701
Conversation
Ports the cpi-guard Token-2022 example to Pinocchio (the anchor example has no native sibling). Unlike the other extension examples, CpiGuard cannot be enabled or disabled through a CPI, so the program cannot initialize it; instead the program exposes a cpi_transfer instruction (a Token-2022 TransferChecked CPI, reading the mint's decimals from account data) and the example demonstrates the guard's effect. The litesvm test creates a source account with CpiGuard enabled (client-side) and funded, then shows the program's CPI transfer is rejected while the guard is on and succeeds once it is disabled, asserting the destination balance. Matches the kit + litesvm template of the other token-2022 pinocchio examples.
Greptile SummaryThis PR adds a Pinocchio implementation and LiteSVM test for demonstrating Token-2022 CPI Guard behavior.
Confidence Score: 4/5The program and test behavior appear sound, but the broken artifact paths in both deployment commands should be corrected before merging. The build emits Files Needing Attention: tokens/token-2022/cpi-guard/pinocchio/cicd.sh; tokens/token-2022/cpi-guard/pinocchio/package.json Important Files Changed
Reviews (1): Last reviewed commit: "token-2022 cpi-guard: add pinocchio exam..." | Re-trigger Greptile |
| # Run this bad boy with "bash cicd.sh" or "./cicd.sh" | ||
|
|
||
| cargo build-sbf --manifest-path=./program/Cargo.toml --sbf-out-dir=./program/target/so | ||
| solana program deploy ./program/target/so/program.so |
There was a problem hiding this comment.
There was a problem hiding this comment.
This cicd.sh (and the matching deploy npm script) is a verbatim copy of the template used by every merged pinocchio Token-2022 example — immutable-owner, permanent-delegate, interest-bearing, and transfer-fee all ship the identical solana program deploy ./program/target/so/program.so line. It's a reference/convenience script and is not exercised by CI or the tests: the build-and-test flow builds with --sbf-out-dir=./tests/fixtures, which produces and loads the crate-named token_2022_cpi_guard_pinocchio_program.so, so all checks pass.
You're right that the standalone deploy path wouldn't resolve the crate-derived filename as-is. Since it's identical across the whole merged series, I've kept it consistent here rather than diverging in a single example — correcting it is better done as a repo-wide follow-up so every example stays in sync. Happy to open that separately if the maintainers want it.
There was a problem hiding this comment.
That context makes sense. Since this is a non-CI reference script intentionally kept consistent with the other merged Pinocchio Token-2022 examples, I agree this should be handled as a repo-wide follow-up rather than changed in isolation. I’m treating the artifact-path mismatch as non-blocking for this PR.
There was a problem hiding this comment.
Opened the repo-wide fix as #702 — it switches the deploy path to a *.so glob across all affected native and pinocchio examples so every example stays consistent.
What
Adds a Pinocchio implementation of the Token-2022
cpi-guardexample. The example previously had only ananchorversion (nonative), so this is a fresh port, following the same kit + litesvm template as the other Token-2022 pinocchio examples.How it works — and why it's different
The
CpiGuardextension prevents privileged token operations (transfer, burn, approve, close) from being performed through a CPI when they're authorized by the account owner — a protection against malicious programs redirecting funds.Crucially, CpiGuard cannot be enabled or disabled through a CPI (Token-2022 requires those to be transaction-level). So — unlike every other extension example — the program cannot initialize this extension. Instead:
cpi_transferinstruction that performs a Token-2022TransferCheckedCPI (variant12) from a source account to a destination, signed by the source's owner. It reads the mint'sdecimalsdirectly from the mint account data (offset 44) so the checked transfer matches the mint.Test
litesvm+@solana/kit. The test:getEnableCpiGuardInstruction), funded with tokens, plus a plain destination account.cpi_transferwhile the guard is enabled → asserts it is rejected (FailedTransactionMetadata).cpi_transferagain → asserts it succeeds, and that the destination balance is1.The success-after-disable (with the balance moving) proves the guard is the cause of the rejection, not a mechanical transfer error.
Verified locally:
cargo build-sbf, the litesvm test,tsc --noEmit, Prettier,cargo fmt --check, Clippy, andpnpm install --frozen-lockfileall clean.