Trustless on-chain Bitcoin hashprice oracle powered by Bitcoin SPV (Simplified Payment Verification) proofs. No trusted intermediary — anyone can permissionlessly submit Bitcoin block headers and coinbase merkle proofs directly to the contract.
This repository contains:
- Smart Contracts (
/contracts) —HashpriceBTC(BTC-denominated hashprice via SPV) andHashpriceUSD(USD-denominated, combinesHashpriceBTCwith a Chainlink BTC/USD feed). Both implementAggregatorV3Interface. - Keeper (
/keeper) — Automated bot that relays Bitcoin block headers and coinbase merkle proofs to the on-chain oracle, keeping the hashprice feed current. - Subgraph Indexer (
/indexer) — A Graph Protocol subgraph that indexes oracle updates and provides historical hashprice data with hourly/daily aggregations.
Bitcoin network
│ block headers + coinbase merkle proofs
▼
[ keeper ] ──────────────────────────────────► [ HashpriceBTC ]
│
latestRoundData() → hashprice in BTC
│
▼
[ HashpriceUSD ]
│ ▲
latestRoundData() │
│ └─── [ Chainlink BTC/USD ]
│ (any AggregatorV3Interface)
▼
latestRoundData() → hashprice in USD
HashpriceBTC is a Bitcoin SPV contract — it stores Bitcoin block headers on-chain and verifies coinbase transactions via merkle proofs, without trusting any off-chain data source.
Each submitted block provides:
- An 80-byte block header, from which the contract extracts difficulty target, timestamp, and previous block hash, and verifies proof-of-work
- A coinbase merkle proof, which proves the coinbase transaction is the first transaction in that block
From the verified coinbase (block subsidy + fees) and the on-chain difficulty, the contract computes the hashprice — the expected revenue per petahash per day — using a 144-block Simple Moving Average over fees, matching the Luxor hashprice index.
Key properties:
- Permissionless — any address can submit headers and proofs; no owner, no admin key
- Trustless — the contract rejects any submission that fails PoW or merkle verification; a malicious keeper cannot corrupt the feed
- Reorg-aware —
submitBlocks()handles chain reorganizations by accepting a new chain of headers that replaces the current tip - Chainlink-compatible — implements
AggregatorV3Interface; output is 100 TH/s per day priced in BTC (8 decimals)
Why SPV? SPV verification requires only 80-byte block headers and a merkle path — no full node, no trusted oracle, no multisig. The same primitive underpins Bitcoin light clients and cross-chain bridges like BTC Relay.
For a detailed breakdown of every validation check — what is included, what is deliberately excluded, and why — see docs/BLOCK_VALIDATION.md.
HashpriceUSD is a thin aggregator contract that combines two AggregatorV3Interface feeds to produce a USD-denominated hashprice:
hashprice (USD) = hashprice (BTC) × BTC/USD price
It accepts any AggregatorV3Interface-compatible BTC/USD feed at deploy time (e.g. Chainlink on mainnet, a custom feed on other networks), making it chain-agnostic. Staleness semantics are conservative: updatedAt reflects the older of the two upstream feeds, so consumers checking staleness always see the bottleneck.
Both contracts implement AggregatorV3Interface, so they are drop-in compatible with any protocol that reads Chainlink price feeds.
The keeper monitors the on-chain oracle height against the Bitcoin tip and submits missing blocks as a batch. It is runtime-agnostic and ships adapters for Node.js, AWS Lambda, and Cloudflare Workers. See keeper/README.md for setup and configuration.
cd contracts
pnpm install
pnpm test
pnpm compilecd keeper
pnpm install
cp .env.example .env
# fill in .env
pnpm devcd indexer
yarn install
# Configure .env from .env.example
yarn codegen
yarn buildCurrent gas numbers are tracked in gas-benchmark.md and regenerated by running the gas benchmark test:
cd contracts
npx hardhat test tests/HashpriceBTC/gas-benchmark.test.tsMIT