Skip to content

Add Token-2022 cpi-guard Pinocchio example - #793

Open
MarkFeder wants to merge 5 commits into
solana-foundation:mainfrom
MarkFeder:tokens-token-2022-cpi-guard-pinocchio
Open

MarkFeder wants to merge 5 commits into
solana-foundation:mainfrom
MarkFeder:tokens-token-2022-cpi-guard-pinocchio

Conversation

@MarkFeder

@MarkFeder MarkFeder commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Linked issue

Fixes #786

Replaces #701, which the PR-hygiene bot closed before the issue was accepted; GitHub doesn't let the author reopen it.

What and why

Adds a Pinocchio version of tokens/token-2022/cpi-guard, which only had an Anchor one, following the same kit + LiteSVM template as the other Token-2022 Pinocchio examples.

CpiGuard stops privileged token operations (transfer, burn, approve, close) authorized by the account owner from running through a CPI. Token-2022 doesn't allow enabling or disabling the guard through a CPI either, so unlike the other extension examples the program can't initialize it. Instead:

  • The program exposes one cpi_transfer instruction: a Token-2022 TransferChecked CPI (variant 12) from source to destination, signed by the source's owner. It checks that Token-2022 owns the mint account, then reads decimals from it (offset 44) so the checked transfer matches the mint.
  • The test enables and disables the guard client-side and shows its effect on that CPI.

The JS dependencies match the versions #765 set for the other non-anchor examples.

Testing

pnpm install --frozen-lockfile, tsc --noEmit, pnpm build, pnpm build-and-test and pnpm audit in a Linux container, plus cargo fmt --check, cargo clippy -D warnings and prettier --check:

Token-2022 CPI Guard (Pinocchio)
  ✔ Blocks a CPI transfer while CpiGuard is enabled and allows it once disabled
  ✔ Rejects a mint that Token-2022 does not own, before any CPI
2 passing
No known vulnerabilities found

The test creates a mint and a funded source account with CpiGuard enabled, asserts cpi_transfer fails (FailedTransactionMetadata), disables the guard, and asserts the same call succeeds and the destination balance is 1. The success after disabling shows the guard caused the rejection.

The second test passes a byte-for-byte copy of a real mint owned by the System Program, and asserts the program fails before any Token-2022 CPI and no tokens move. With the owner check deleted, this test fails (the fake mint reaches TransferChecked).

bash cicd.sh and pnpm run deploy both name token_2022_cpi_guard_pinocchio_program.so, the file cargo build-sbf writes; checked in Linux with a real build (same check as #794). The name is explicit rather than a *.so glob because pnpm runs scripts through cmd.exe on Windows, which doesn't expand globs.

AI disclosure

Check exactly one. See CONTRIBUTING.md.

  • No AI tooling was used beyond editor autocomplete.
  • AI tooling was used. Tool and extent: Claude Code helped write the program, the tests and this description; I reviewed the changes and the build and test results.

MarkFeder and others added 2 commits November 4, 2026 19:19
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.
Matches the versions solana-foundation#765 set for the other non-anchor examples (kit 8.5, mocha 12, typescript 7) and adds the same pnpm-workspace.yaml overrides, which clears pnpm-audit. The signer role in the hand-built instruction takes 'as const' so kit 8 keeps it as a signer role, as the sibling tests on main do.
@greptile-apps

greptile-apps Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no new actionable issues were found.

Summary

Adds a Pinocchio example showing how Token-2022’s CpiGuard blocks transfers made through another program.

  • Pinocchio's one-unit token transfer shows when CpiGuard blocks a CPI.
  • The example rejects mints that Token-2022 does not own.

Reviews (4) · Last reviewed commit: "token-2022 cpi-guard pinocchio: check th..." · Reviewed by Greptile

cargo build-sbf names the artifact after the crate, so deploy the *.so in the output dir instead of program.so, and stop cicd.sh if the build fails. pinocchio-token-2022 now exists in the workspace, so the comment says the instruction is hand-built to show its layout rather than claiming there is no crate.
pnpm runs package.json scripts through cmd.exe on Windows, which does not expand the *.so glob. Name the file cargo build-sbf writes instead, matching solana-foundation#794.
cpi_transfer read decimals from whatever account was passed as the mint. Token-2022 would still reject a fake mint inside TransferChecked, but an example should show the check: only read a mint's bytes once Token-2022 owns it. The new test passes a byte-for-byte copy of a real mint owned by the System Program and asserts the program fails before any Token-2022 CPI and no tokens move.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

token-2022/cpi-guard: add a Pinocchio version

1 participant