Oracle data for EVM dApps
How to read Chainlink price feeds, use data feeds in your contracts, and follow best practices. A concise technical reference for EVM developers.
Find the right price feed address using the Chainlink Feed Registry or documentation. Each feed returns a quote currency (usually USD) per unit of the base asset.
// AggregatorV3Interface at feed address address feed = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; // ETH/USD
Use latestRoundData() to fetch the current price and round metadata.
function getPrice() external view returns (int) { AggregatorV3Interface feed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); (, int price, , , ) = feed.latestRoundData(); return price; }
Check round completeness, staleness, and price > 0 before using the data.
function validatePrice() external view returns (uint) { (, int price, uint startedAt, uint updatedAt, uint answeredInRound) = feed.latestRoundData(); require(price > 0, "negative price"); require(answeredInRound >= roundId, "stale round"); require(block.timestamp - updatedAt < 1 hours, "stale feed"); return uint(price); }
Compute a TWAP-like median across multiple feeds for resilience against manipulation.
function aggregatePrice(address[] memory feeds) external view returns (uint) { uint[] memory prices = new uint[](feeds.length); for (uint i; i < feeds.length; i++) { (, int p, , , ) = AggregatorV3Interface(feeds[i]).latestRoundData(); prices[i] = uint(p); } return median(prices); }
Arbitrum, Optimism, and Polygon use sequencer-enabled feeds. Check the sequencer uptime feed before reading prices.
function getL2Price() external view returns (uint) { (, int seq, , uint last, ) = sequencerUptime.latestRoundData(); require(seq == 0, "sequencer down"); require(last != 0, "no data"); (, int price, , , ) = feed.latestRoundData(); return uint(price); }
Cache feed addresses, batch reads, and avoid unnecessary rounds in loops. Price feeds update every ~1 hour on mainnet.
// Cache feeds in constructor, not per-call AggregatorV3Interface immutable ethUsd; uint immutable heartbeat = 1 hours;