An open oracle for every T-bill.
BillOracle stores Treasury's seven daily bill rates and the list of every outstanding bill by CUSIP, and prices any of them on read. We found no open, free, per-bill T-bill oracle on chain; the only per-bill source is licensed.
Who offers T-bill prices on chain today
| Provider | What it publishes | Per-bill price? | Access |
|---|---|---|---|
| Chainlink DataLink with Tradeweb | FTSE US Treasury closing prices at 3 pm and 4 pm New York, bills included; a registered benchmark | Yes | Licensed: the provider sets access rules; applied for by form |
| Pyth | Overnight rates, 2–30 year yields and prices, bill ETFs | No | Pull model; current values need an API key |
| Chronicle Verified Asset Oracle | Fund values and proof of assets (Superstate USTB, BUIDL verification) | No, fund level | Per issuer |
| RedStone | Fund values for Securitize funds (BUIDL, VBILL) | No | Per issuer |
| DIA Value | Values computed from on-chain state | No | n/a |
Design
- Store the curve, not the prices. Seven rates and a CUSIP-to-maturity map cover every bill, including next week's. Posting costs about 70,000 gas a day, roughly $0.001 on Base mainnet.
- Exact pricing.
priceOfinterpolates the rate as an exact fraction. An earlier version rounded the rate to millionths first, which cost up to $0.26 per $1M on a 92-day bill; it was redeployed before any bill was bought. - Staleness. A price is refused 4 days after the end of its data date, enough for a weekend plus a holiday.
- Dates move forward only. A date may be re-posted as a correction, never moved back.
Interface
function postRates(uint64 asOf, uint32[7] rates) // poster; rates in millionths (3.90% = 39_000)
function setBills(bytes9[] cusips, uint64[] maturities) // poster; maturities at 00:00 UTC
function priceOf(bytes9 cusip) view returns (uint256 pricePer100, uint256 rate, uint256 daysLeft)
function priceAt(uint256 maturity) view returns (uint256 pricePer100, uint256 rate, uint256 daysLeft)
function rateFor(uint256 daysLeft) view returns (uint256) // display: floored to millionths
function isFresh() view returns (bool)
Live on Vibenet: 0xF49A3EFcfb7f0D82645E46CE4110445608C35175, with 52 outstanding bills from 912797UM7 to 912797WT0 and Treasury's 2 November 2026 rates.
Version 1, for Base Sepolia
- Three independent signers (LIUM, NFH and a partner) each fetch and sign; an update lands when two match.
- A jump limit refuses an implausible day-over-day move without a second confirmation.
- Chainlink-style feed adapters per tenor and per CUSIP, so lending markets can read it without custom code.
Limits we state plainly
- Prices come from Treasury's curve, not from trades. Older bills can trade slightly off the curve; trade-level prices need Tradeweb, ICE or Bloomberg, all licensed.
- Treasury's FedInvest page appears to list end-of-day prices per security, but refused automated access (HTTP 403). Its terms need checking by hand before it could be a second source.