Skip to content

feat(oracles/pyth): add pinocchio example - #707

Open
MarkFeder wants to merge 1 commit into
solana-foundation:mainfrom
MarkFeder:oracles-pyth-pinocchio
Open

feat(oracles/pyth): add pinocchio example#707
MarkFeder wants to merge 1 commit into
solana-foundation:mainfrom
MarkFeder:oracles-pyth-pinocchio

Conversation

@MarkFeder

Copy link
Copy Markdown
Contributor

What

Adds a Pinocchio implementation of the Pyth oracle example (the first pinocchio example under oracles/), alongside the existing anchor version. A single read_price instruction reads a Pyth pull-oracle PriceUpdateV2 account and logs its price fields.

How it works

There is no Pyth SDK for Pinocchio, so the account is parsed by hand:

  1. Validate the account's owner is the Pyth receiver program (rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ) and its 8-byte anchor discriminator — so the program never trusts the price data of an arbitrary account (what anchor's Account<PriceUpdateV2> does for free).
  2. Locate the PriceFeedMessage: it follows the discriminator (8), write authority (32), and the VerificationLevel. That enum is variable-size (Full = 1 byte, Partial { num_signatures } = 2), so the message offset is computed from it.
  3. Read price (i64), conf (u64), exponent (i32), and publish_time (i64) by little-endian byte offset and log them.

Test

litesvm + @solana/kit. Since litesvm doesn't bundle Pyth, the test constructs a mock PriceUpdateV2 account with known values and injects it via setAccount, then:

  • asserts the program logs the parsed price / conf / exponent / publish_time, and
  • asserts a second account not owned by the Pyth receiver program is rejected.
Pyth (Pinocchio)
  ✔ Reads the price from a Pyth price update account
  ✔ Rejects an account not owned by the Pyth receiver program
2 passing

Verified locally: cargo build-sbf, the litesvm tests, tsc --noEmit, Prettier, cargo fmt --check, Clippy, and pnpm install --frozen-lockfile all clean. (The deploy script uses the *.so glob per #702.)


AI use: I chose the approach (hand-parsing the PriceUpdateV2 layout, validating owner + discriminator, the mock-account test) and verified the layout and discriminator against the pyth-solana-receiver-sdk / pythnet-sdk sources; implementation and tests were written with Claude Code and reviewed by me.

@MarkFeder
MarkFeder requested a review from dev-jodee as a code owner August 30, 2026 00:07
@greptile-apps

greptile-apps Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a Pinocchio-based Pyth oracle example that manually validates and parses PriceUpdateV2 accounts.

  • Validates the Pyth receiver owner, Anchor discriminator, and verification-level discriminant before reading price fields.
  • Adds LiteSVM coverage for valid price parsing, wrong-owner rejection, and unknown verification-level rejection.
  • Adds workspace, build, deployment, and TypeScript package configuration for the example.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
oracles/pyth/pinocchio/program/src/instructions/read_price.rs Validates the owner, account discriminator, and both supported verification variants before safely reading fixed-width price fields; the previously reported unknown-variant issue is fixed.
oracles/pyth/pinocchio/tests/test.ts Exercises successful field parsing and rejection of both wrong-owner accounts and unsupported verification discriminants.
oracles/pyth/pinocchio/program/src/processor.rs Routes the example’s single instruction directly to the price-reading handler.
oracles/pyth/pinocchio/program/src/lib.rs Defines the no-std Pinocchio entrypoint and panic handler.
oracles/pyth/pinocchio/program/Cargo.toml Configures the new Pinocchio Solana program and its runtime dependencies.
oracles/pyth/pinocchio/package.json Adds build, deployment, and LiteSVM test commands for the example.

Reviews (2): Last reviewed commit: "feat(oracles/pyth): add pinocchio exampl..." | Re-trigger Greptile

Comment on lines +54 to +58
let message_offset = if verification_level == VERIFICATION_LEVEL_FULL {
VERIFICATION_LEVEL_OFFSET + 1
} else {
VERIFICATION_LEVEL_OFFSET + 2
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unknown verification variants accepted

Every verification-level byte other than Full is interpreted as Partial, so a receiver-owned account with a malformed or unsupported Borsh enum discriminant can return success and log unrelated bytes as price fields instead of being rejected.

Suggested change
let message_offset = if verification_level == VERIFICATION_LEVEL_FULL {
VERIFICATION_LEVEL_OFFSET + 1
} else {
VERIFICATION_LEVEL_OFFSET + 2
};
let message_offset = match verification_level {
VERIFICATION_LEVEL_FULL => VERIFICATION_LEVEL_OFFSET + 1,
0 => VERIFICATION_LEVEL_OFFSET + 2,
_ => return Err(ProgramError::InvalidAccountData),
};

Knowledge Base Used:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 0e328ad. The verification level is now matched explicitly (Full → 1 byte, Partial → 2 bytes, anything else → InvalidAccountData), so a receiver-owned account with a malformed enum discriminant is rejected rather than misparsed. Added a test that a PriceUpdateV2 with an unknown verification level (2) is rejected — 3 tests passing.

@MarkFeder
MarkFeder force-pushed the oracles-pyth-pinocchio branch from b89fd70 to d5c713d Compare August 30, 2026 00:12
Adds a Pinocchio implementation of the Pyth oracle example, the first pinocchio
example under oracles/. The single read_price instruction reads a Pyth pull
oracle PriceUpdateV2 account and logs its price fields.

There is no Pyth SDK for Pinocchio, so the account is parsed by hand: the
program checks the account's owner (the Pyth receiver program) and the anchor
account discriminator before trusting the data, then reads the price, confidence,
exponent, and publish time by byte offset. The account's VerificationLevel is a
variable-size Borsh enum, so the price message offset is computed from it.

The litesvm test injects a mock PriceUpdateV2 account with known values via
setAccount and asserts the program logs the parsed fields, plus a second case
that a non-Pyth-owned account is rejected.
@MarkFeder
MarkFeder force-pushed the oracles-pyth-pinocchio branch from d5c713d to 0e328ad Compare August 30, 2026 00:12
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.

1 participant