← Protocols
Tellor
01Description

Permissionless, decentralized oracle where anyone can stake TRB to report data. Reporters submit values for a `queryId` and consumers read with a built-in dispute window — disputed values are removed and the reporter's stake is slashed.

02Best for
  • 01permissionless / censorship-resistant data feeds
  • 02long-tail data not covered by managed oracles
  • 03custom data via `queryData` / `queryId`
  • 04cost-sensitive apps (no per-read fee)
  • 05sovereign chains and L2s without major oracle providers
03Install
  • pnpm add usingtellor
  • forge install tellor-io/usingtellor
04Environment variables
VariableScopeDescription
TELLOR_ORACLE_ADDRESSClientTellorMaster / Oracle contract address on the target chain. See docs.tellor.io/tellor/the-basics/contracts-reference.
05Prompt snippet
Inherit `UsingTellor` from `usingtellor/contracts/UsingTellor.sol` and pass the Tellor oracle address to the constructor. Build a `queryId` as `bytes32(keccak256(queryData))` where `queryData` is the abi-encoded `(string queryType, bytes parameters)` (e.g. `abi.encode('SpotPrice', abi.encode('eth','usd'))`). Read with `(bytes memory value, uint256 timestampRetrieved) = _getDataBefore(queryId, block.timestamp - DISPUTE_BUFFER)` — ALWAYS subtract a dispute buffer (typically 15-60 minutes) so disputed reports are excluded; then `abi.decode(value, (uint256))` for prices. For testing inherit `TellorPlayground` and seed values with `submitValue(queryId, value, nonce, queryData)` then `getCurrentValue(queryId)`. To fund queries with tips call `IAutopay.tip(queryId, amount, queryData)`.
06Gotchas
  • ALWAYS use `_getDataBefore(queryId, block.timestamp - bufferTime)` — NEVER `getCurrentValue` for high-value reads; without a buffer you can read a value that is still inside the 12-hour dispute window and get rolled back when slashed.
  • Tellor is permissionless: anyone with TRB stake can report. Bad data is corrected via the dispute system (12h window, dispute fee in TRB) — design assuming any single value MAY be wrong until it's old enough to be undisputable.
  • `queryId` is `keccak256(queryData)`; misencoding `queryData` (wrong types, wrong order, wrong casing on symbols like `eth` vs `ETH`) silently maps to a different feed that may have no reports at all.
  • Decimal scaling is per-query-type: `SpotPrice` returns a `uint256` scaled to 1e18. Other query types (e.g. `EVMCall`, `NumericApiResponse`) follow their own spec docs — never assume 8 or 18 decimals.
  • Push vs pull: Tellor is pull from the consumer's perspective (you read on-demand) but reports are written push-style by reporters who must be tipped/incentivized; an unpopular `queryId` may have NO recent value — handle empty `bytes` returns.
  • Network fees: reads are free (just gas), but to ensure fresh reports you must `tip` the queryId in TRB via `Autopay`; budget for tips per heartbeat or use a managed reporter.
  • Per-chain oracle addresses differ (Ethereum vs Polygon vs Arbitrum) and reporter sets / tipping economics are independent — verify the oracle address and tipping pool per chain before deploying.
07Alternatives