Events
PriceUpdated
Emitted every time a price is successfully pushed on-chain by the relayer network.
When it fires:
- On every successful deviation-triggered update
- On every successful heartbeat-triggered update
- Never fires on failed or rejected submissions
assetIdis indexed — you can filter logs for a specific asset without downloading all eventstimestampmatches thelastUpdateTimefield returned bygetAssetInfo— the two values are always in sync- One event is emitted per asset per update — batch submissions emit one event per asset
Listening to Events
JavaScript — Real-Time with ethers.js
Listen for live price updates as they happen on-chain:WebSocket connections are required for real-time event listening. HTTP RPC providers do not support
eth_subscribe. Use a dedicated WebSocket provider — Alchemy, QuickNode, or Infura — not the public Base RPC endpoint.JavaScript — Historical Query with ethers.js
Query past price update events for a specific asset over a block range:Python — Real-Time with web3.py
Basescan — Manual Event Inspection
To inspect price update events without writing code:1
Open the Events tab
Go to the contract on Basescan and click the Events tab: basescan.org/address/0xA9F17344689C2c2328F94464998db1d3e35B80dC#events
2
Filter by asset ID
Use the topic filter to narrow results to a specific asset. The
assetId parameter is indexed — enter the bytes32 value for the asset you want to inspect as Topic 1.3
Read the event data
Each row shows the transaction hash, block number, and decoded event parameters —
price, decimal, and timestamp. The price field is the raw scaled integer — divide by 1e18 for the human-readable value.Building a Price History Database
For analytics dashboards, historical price charts, or audit trails, persistPriceUpdated events to a database as they arrive:
Indexing with The Graph
For production-grade historical data access, indexPriceUpdated events using The Graph:
Event Monitoring Best Practices
Use WebSockets for real-time feeds, HTTP for historical queries. WebSocket providers supporteth_subscribe for live event streaming. HTTP providers require polling with queryFilter — adequate for historical data but not for real-time monitoring.
Store raw values alongside human-readable values. Always persist both raw_price (the unscaled int256) and the human-readable price in your database. The raw value is lossless — the human-readable conversion may lose precision depending on your numeric type. If you ever need to reprocess historical data, the raw value is the authoritative source.
Index by assetId and updated_at. These are the two axes on which you will query price history — “all updates for CNGN/USD” and “all updates in the last 24 hours.” Both should be indexed in your database for acceptable query performance at scale.
Handle WebSocket reconnections. WebSocket connections to RPC providers drop periodically. Any production event listener must implement reconnection logic — either manually or through a library that handles it automatically.
Backfill from genesis block on first deployment. When deploying a price history database for the first time, backfill all historical PriceUpdated events from the oracle contract’s deployment block before switching to live streaming. Otherwise your historical data will have a gap.
Next Steps
ABI Download
Get the official ABI for use in your monitoring scripts and indexers.
Running Price Monitoring
Production-ready monitoring scripts built on the event patterns documented here.

