Integrate
Solidity
Read Tachi prices from any EVM contract through IPriceOracle.
Integrate
Read Tachi data from Solidity, Clarity or the API.
2 min read 4 sections Testnet
Read a price
The oracle lives at the same address on Base Sepolia and Avalanche Fuji. Read by pair name, or by feed id for slightly cheaper calls. Always pass the age you accept.
CollateralValue.sol
import {IPriceOracle} from "./IPriceOracle.sol";
contract CollateralValue {
IPriceOracle public immutable oracle;
uint256 public constant MAX_AGE = 15 minutes;
constructor(IPriceOracle oracle_) {
oracle = oracle_;
}
/// Value of `shares` SCOM in US dollars, 8 decimals.
function valueOf(uint256 shares) external view returns (uint256) {
// Reverts when the stored price is older than MAX_AGE.
IPriceOracle.PriceData memory p = oracle.getPriceIfFreshByPair("SCOM/USD", MAX_AGE);
require(p.status != IPriceOracle.MarketStatus.Halted, "halted");
return shares * p.price;
}
}Functions
| Function | Returns | What it does |
|---|---|---|
decimals() | uint8 | Always 8. Prices are units of 10⁻⁸ of the quote currency. |
feedIdOf(string pair) | bytes32 | keccak256 of the pair's ASCII bytes. |
getLatestPrice(bytes32 feedId) | PriceData | Newest stored price. Check its age yourself. |
getPriceIfFresh(bytes32 feedId, uint256 maxAge) | PriceData | Reverts when the data is older than maxAge seconds. |
getMarketStatus(bytes32 feedId) | MarketStatus | Open, Closed or Halted. |
getRound(bytes32 feedId, uint32 round) | PriceData | A past accepted price. |
latestRoundData(bytes32 feedId) | round tuple | The familiar round shape, per feed. |
getLatestPriceByPair(string pair) | PriceData | Same as getLatestPrice, by name. |
getPriceIfFreshByPair(string pair, uint256 maxAge) | PriceData | Same as getPriceIfFresh, by name. |
getTickerPrices(string symbol) | TickerPrices | Both the KES and the USD price of one ticker. |
getTickerPricesIfFresh(string symbol, uint256 maxAge) | TickerPrices | Both prices, each checked for age. |
verifyReportIfFresh(bytes32 feedId, SignedUpdate[] updates, uint256 maxAge) | PriceData | Verifies a signed report in your transaction without storing it. |
listedFeeds() | bytes32[] | Every listed feed, in listing order. |
getFeed(bytes32 feedId) | Feed | Pair name, listed flag and latest round. |
isPaused(bytes32 feedId) | bool | True while the guardian has paused the feed. |
Pull a fresh report into your transaction
When the stored price is not fresh enough, fetch the newest signed report from the oracle API and pass it to your contract. The oracle checks every signature, the quorum, the age and the circuit breaker, then returns the price for this transaction only.
PullTrade.sol
/// Pull model: carry a fresh signed report in the same transaction.
function buyWithReport(
bytes32 feedId,
ReportVerifier.SignedUpdate[] calldata updates,
uint256 usdcIn
) external {
// Verifies the signatures, the quorum and the age. Nothing is stored (round is 0).
IPriceOracle.PriceData memory p = oracle.verifyReportIfFresh(feedId, updates, 60);
uint256 shares = (usdcIn * 1e8 * 1e2) / p.price;
// ... settle the trade at p.price
}Reference contract
The pull trade example is deployed on Base Sepolia and Avalanche Fuji at
0x27e986DCf951eA38e3244aaa413CBEF64f59E2c0.Events
solidity
event PriceUpdated(bytes32 indexed feedId, uint32 indexed round, PriceData price);
event FeedListed(bytes32 indexed feedId, string pair);
event FeedDelisted(bytes32 indexed feedId, string pair);Something wrong or missing on this page? Tell us.

