Individual price feeds go stale for hours while others update in seconds
All four of K2’s reserves are priced by the same oracle contract (CCHRZE2K…) through the same batchAdapter source. Their prices do not age together. In one reading on 2026-08-18, SolvBTC was 27 seconds old and XLM 177 seconds old, while USDC was 21,421 seconds old (5h 57m) and PYUSD 41,777 seconds old (11h 36m). Repeated readings minutes apart showed the same split, with the two stale ages advancing in step with wall-clock time — meaning those entries were not being refreshed at all during the observation, rather than being sampled at an unlucky moment.
For scale against K2’s own limits: price_staleness_threshold is 3600 seconds, so the USDC reading exceeded it roughly sixfold and the PYUSD reading elevenfold. The per-asset max_age values are looser — 43,200 seconds for XLM and SolvBTC, 86,400 for USDC and PYUSD — and neither stale reading had reached those.
What this changes about the picture above: the staleness is not the whole oracle going quiet and coming back. The oracle is demonstrably alive and serving some assets within seconds while others sit untouched for hours, through one contract and one source. Freshness here is a property of the individual feed entry, not of the oracle as a whole.
USDC is the reading worth noting rather than PYUSD. PYUSD held about $4 of supplied value at the time and USDC about $54 — both small in absolute terms, but USDC is well above the size line Stenion uses elsewhere, so this is not a question of an abandoned dust market. A lending protocol valuing a stablecoin position off a six-hour-old reading is the observable condition.
What is not being claimed: nothing here says the protocol acted on a stale price. K2’s own code may reject it and revert whatever operation depended on it — that is the same limit noted above, and it applies equally here. What is observable from outside is the age of the price the oracle serves. Nor is any cause implied: an upstream feed pausing, a per-asset configuration, and a deliberate choice all look identical from here.
Every reserve’s price age is now published on each run in the oracleSafety factor’s priceAges component, alongside a count of how many exceed K2’s own threshold. It is reported, not scored — the freshness score already grades the worst of them, and grading the spread again would count the same staleness twice.
Still running as of 2026-08-20. A fresh reading two days after the one above found SolvBTC at 26 seconds, XLM at 71, USDC at 618 and PYUSD at 23,304 (6h 28m) — the same split, from the same oracle, in the same call. Two things are worth taking from the repeat rather than from either reading alone. The condition is a standing property of these feeds and not a moment we happened to catch. And WHICH feed is stale moves: USDC was 21,421 seconds old on 2026-08-18 and 618 seconds old on 2026-08-20, while PYUSD exceeded K2’s 3,600-second threshold on both. So a reader should not take the specific assets named here as the affected set — the pattern is that some entry is hours behind while others are seconds behind, not that it is always this one.
Verify it yourself: Call get_asset_prices_vec_fresh on CCHRZE2K…5BNOMQRMU for the four assets in get_reserves_list on the router (CCTUJZLY…AWNXOJIV6J7) and compare each PriceData.timestamp against the current ledger close time — read them together in one call so the ages are directly comparable. Repeat a few minutes later: an age that grows by the elapsed wall-clock time is an entry that is not being refreshed. Read get_asset_config per asset for source and max_age, and get_oracle_config for price_staleness_threshold.