pyth-evm
Pyth EVM
Pyth Network is a pull-based oracle that delivers high-frequency price data to EVM chains. Unlike push oracles (Chainlink) where oracle nodes update on-chain prices on a schedule, Pyth publishes prices off-chain via Hermes and consumers submit price updates on-chain when they need fresh data. This enables sub-second update latency, lower oracle costs, and prices across 500+ feeds on 70+ chains.
What You Probably Got Wrong
-
Price updates can be front-run -- ALWAYS combine
updatePriceFeeds+ price consumption in a SINGLE transaction. If you exposeupdatePriceFeedsas a standalone public function, an attacker can sandwich your price update: observe the pending update, trade before it lands, then trade after. The ONLY safe pattern is a single function that acceptsbytes[] calldata pythUpdateData, callsupdatePriceFeeds, and immediately reads the price. Never separate update from read. -
Confidence interval matters -- wide confidence = unreliable price. Every Pyth price includes a confidence interval (1 standard deviation). A BTC price of $67,890 with confidence $680 means the true price is between $67,210 and $68,570 with ~68% probability. Reject prices where
conf > price * 0.01(1%) for lending protocols, or your protocol becomes exploitable during high-volatility events. -
Update fee is dynamic -- do NOT hardcode
msg.value. The fee depends on the number of price updates in theupdateData. Always callpyth.getUpdateFee(updateData)first and pass the exact amount asmsg.value. Hardcoding1 weiwill revert when the fee changes. -
getPriceUnsafe()returns arbitrarily stale data. It is only safe to call immediately afterupdatePriceFeedsin the same transaction. In any other context, usegetPriceNoOlderThan(priceFeedId, maxAge)which reverts if the price is too old. -
Pyth uses a PULL model -- prices are NOT already on-chain. You must fetch price update data from Hermes (off-chain) and submit it on-chain. This is the opposite of Chainlink where oracles push updates on a heartbeat schedule. If your contract tries to read a Pyth price without first calling
updatePriceFeeds, you get stale or nonexistent data. -
Price feed IDs are
bytes32, NOT contract addresses. Each feed has a uniquebytes32identifier that is the SAME across all chains. Feed0xff61491a...is always ETH/USD whether you are on Ethereum, Arbitrum, or Base. The Pyth contract address varies by chain, but feed IDs do not. -
Pyth contract addresses VARY by chain. Ethereum and Avalanche use
0x4305FB66699C3B2702D4d05CF36551390A4c69C6. Arbitrum, Optimism, and Polygon use0xff1a0f4744e8582DF1aE09D5611b887B6a12925C. BNB Chain uses0x4D7E825f80bDf85e913E0DD2A2D54927e9dE1594. Always look up the correct address for your target chain.