# Pyth Price Feeds

> Pyth pull price feeds on Hedera. Use when integrating Pyth on Hedera (testnet 296 / mainnet 295), fetching Hermes update payloads, paying updatePriceFeeds, calling getPriceNoOlderThan, checking confidence, or normalizing signed price + expo to 18 decimals.

- Skill: `hedera-dev/pyth-price-feeds` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add hedera-dev/pyth-price-feeds`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hedera-dev/pyth-price-feeds/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: hedera-dev (https://skillmd.com/u/hedera-dev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/hedera-dev/pyth-price-feeds

---


# Pyth Price Feeds (Hedera)

**Pull pattern:** Pyth is not a fire-and-forget push feed. Fresh reads usually need a Hermes payload submitted on-chain (payable) **before** `getPriceNoOlderThan`.

```text
Hermes → updatePriceFeeds{value: fee}(updateData) → getPriceNoOlderThan(priceId, maxAge)
```

Consumers may wrap Pyth behind a local interface; that is optional. Do not assume a project-specific adapter name.

## Quick Reference

| Piece | Role |
| ----- | ---- |
| Pyth contract | Network `IPyth` address |
| Price ID | `bytes32` feed id (not an aggregator address) |
| Update | Payable `updatePriceFeeds` with Hermes `updateData` |
| Fee | `getUpdateFee(updateData)` — `msg.value` must cover it |
| Read | `getPriceNoOlderThan(priceId, maxAge)` |
| Confidence | Reject when `conf > uint64(price)` |
| Scale | Signed `price` + `expo` → consumer decimals (often 18) |

**Hedera chain IDs:** testnet `296`, mainnet `295`.

See [references/hedera-feeds.md](references/hedera-feeds.md) for where to source the Pyth contract and price IDs. See [references/examples.md](references/examples.md) for update / read / expo sketches.

## Critical: Update Before Fresh Reads

If the on-chain price is older than your staleness bound, fetch Hermes update data and submit it:

```solidity
function updatePrice(bytes[] calldata updateData) external payable {
    uint256 fee = PYTH.getUpdateFee(updateData);
    if (msg.value < fee) revert UpdateFeeTooLow(msg.value, fee);
    PYTH.updatePriceFeeds{ value: msg.value }(updateData);
}
```

Hedera `msg.value` is tinybars via JSON-RPC — attach enough native value for the Pyth fee. Do not treat a stale `getPriceUnsafe` as a valid trading price.

## Critical: Confidence And Signed Expo

After `getPriceNoOlderThan`:

| Check | Why |
| ----- | --- |
| `publishTime != 0` | Incomplete |
| `price > 0` | Invalid / non-positive |
| `conf > uint64(price)` | Confidence wider than the price |
| Normalize `expo` | `expo` is signed; not the same as ERC-20 decimals |

```solidity
PythStructs.Price memory price = PYTH.getPriceNoOlderThan(priceId, maxStaleness);
if (price.publishTime == 0) revert IncompleteRound();
if (price.price <= 0) revert InvalidPrice();
if (price.conf > uint64(price.price)) revert InvalidConfidence();
```

## Checklist

When implementing or reviewing Pyth on Hedera:

- [ ] Pyth contract + price IDs taken from Pyth Hedera / Hermes docs (not Ethereum defaults)
- [ ] Hermes payloads submitted with sufficient `msg.value` before relying on a fresh price
- [ ] Reads use `getPriceNoOlderThan` (or equivalent max-age API), not unbounded unsafe prices for trading
- [ ] Confidence wider than price reverts
- [ ] Signed `expo` normalized to the consumer scale
- [ ] Chain ID is `295` or `296` (or the project’s documented Hedera network)

## References

- [references/examples.md](references/examples.md) — update, read, and expo sketches
- [references/hedera-feeds.md](references/hedera-feeds.md) — where to source Pyth contract and price IDs
- [Pyth Price Feeds](https://docs.pyth.network/price-feeds)
- [Pyth EVM contract addresses](https://docs.pyth.network/price-feeds/core/contract-addresses/evm)
- [Hermes price feeds](https://hermes.pyth.network/v2/price_feeds)

