kaspulse · what changed, and when

What changed, and when

The project’s own history, in one place. It used to be narrated on the landing page. It moved here on 2026-08-25, because a visitor who has never heard of a covenant does not need to read an engineering diary before they can see a price.

Dated measurements and security corrections remain public, including the findings that led us to remove features. They are historical evidence, not a promise about today’s market conditions or a production-readiness guarantee.

Public protocol history, private service implementation.

KasPulse is a proprietary hosted service. This page explains what changed for API consumers and keeps the relevant security evidence accessible. Use the API integration guide to connect an application. Historical measurements keep their dates; corrections are called out explicitly.

2026-08-26KCC20 tokens gained registry names; the temporary name table was removed

This change added kascov’s KRON registry metadata: listed_name, listed_ticker, listed_decimals, listed_known, listed_checks_passed, listed_list_name and listed_art_url on every KCC20 feed. The site shows the familiar ticker when — and only when — the wire says the publisher is KRON, that it knows this exact covenant id, and that every testable check passed. At the time of this entry, all 7 priced markets qualified; none published a claimed_ticker.

What that check actually proves, stated once so it cannot drift. kascov matched the list’s testable statements — creator key, genesis txid, curve covenant — against its own chain index. So the LISTING is bound to that covenant. It did not verify the name or the ticker string: those are the registry’s labels, not on-chain facts. A registry could list a token as “BITCOIN” and every structural check would still pass. Earlier wording on the site called listed_* “checked KRON-registry metadata”, which reads as though the name had been checked. It had not. The browser wording was corrected to match the API’s actual trust boundary, and the website and verification clients now carry the distinction above.

The correction, in full. For one day — 2026-08-25 — an unreleased website revision carried a frozen seven-entry table of covenant id → ticker/name, used as a bridge for API versions that predated the listed_* fields. It rendered the seven tickers under a “KRON registry” badge with the sentence “7 of 7 markets have a checked human label from the KRON registry”, while the wire it was describing carried no such field at all. That count was a tautology of the frozen table, not a measurement, and the page had no way to notice a delisting or a re-ticker. It never reached the deployed site. It was deleted on 2026-08-26 along with the badge that announced it. Regression checks require a feed with no qualified listed_* metadata to fall back to its ID-derived codename.

The rule that replaces it: if a feed carries no listed_*, render the derived codename and say nothing more — never a label bundled with the page.

2026-08-25The site was rewritten for people who are not developers

The landing page ran eight sections and opened, in its status strip, with a sentence about a 32-byte record length pin. That is an implementation detail, not an introduction to an oracle. The rewrite led newcomers through six clear sections: use cases, live prices, the oracle workflow, browser verification, honest limits, and practical next steps. This page exists so that the history it used to narrate is still readable by anyone who wants it.

What left the site’s main surfaces (landing, #/feeds, feed pages, #/l1, the #/dev introduction) and landed here:

  • the 2026-08-24 deletion of the 58 L2 KRC-20 feeds and the measurement that killed them (below);
  • the 2026-07-27 covenant-signature withdrawal and the kaspulse/cov/v2 replacement (below and in the signed-message specification);
  • the bond redeem’s 32-byte record length pin, its TN10 re-run and the txid prefixes that prove it (below);
  • the krc20krc20-l2 → deleted kind renames (below, and the API reference).

Nothing that is still true about the product left with it. The five disclosures the site is built on — the kascov dependency, testnet-only consumers with no mainnet key, one operator holding all five keys, derived token identity, and the bare gate’s anyone-can-spend property — are all still on the site, one sentence each, each linking to its full reasoning. The integration guide’s trust limits retain the safety boundaries relevant to consumers. The 2026-07-27 issue remains the reason old unbound covenant attestations must not be used.

2026-08-25The bond redeem gained a 32-byte record length pin

bond_redeem grew an OpSize <32> OpNumEqualVerify pin on each of the two records it compares, and the TN10 equivocation loop was re-run the same day against those exact bytes rather than against the earlier script.

  • 3 TKAS bonded at P2SH kaspatest:ppeqp2ww…82tq49ndlxnq
  • deploy 1af295c8…775b → slash ff02cf22…e376
  • both is_accepted: true on api-tn10.kaspa.org
  • the slash input’s witness carries the redeem verbatim: 108 bytes, blake2b = the deploy output’s script hash, and the length pin appears twice, over two records differing only in mantissa (2 900 000 vs 5 800 000) at the same pair id and round 42

Why it matters: without the pin, the oracle’s own published kaspulse/cov/v2 preimages could be mistaken for double-signing evidence by the old comparison. The pin rejects that wrong input shape. Honest updates at different rounds, identical prices, forged second signatures, and published cov/v2 or v2 ASCII messages do not constitute a valid double-signing proof. Two genuinely signed, different prices for the same slot do; the comparison includes exponent changes.

Testnet only. There is no project mainnet key or audited mainnet run. The experiment does not establish a mainnet bond protecting the hosted API.

2026-08-24The L2 KRC-20 tier was deleted, and here is the measurement that killed it

Preserved as a dated measurement. Nothing on the current site can recompute it: the feeds are gone. That is why it carries its date and its method.

Measured 2026-08-24, on the live deploy the morning the tier was deleted: the 58 Kasplex / Igra EVM KRC-20 pool feeds had a median reserve touch age of 11.5 days (oldest 248.7), and 55 of 58 markets could be moved 10% for under $250 — median $14.59. They were pool STATE reads, not executed trades, and 51 of 58 had exactly one pool behind them. kaspulse published those numbers next to every one of those prices and then removed the tier rather than keep headlining a count. The two depth formulas are not directly comparable; the caveat is explained below.

The accompanying decision:

kaspulse used to publish 58 Kasplex / Igra EVM KRC-20 pool feeds beside these seven, and used to headline the total. They are removed, not demoted: the EVM RPC reads, the pool auto-discovery, the WKAS peg check and the krc20-l2 kind are out of the codebase, so there is no dormant surface left to accidentally re-enable. The measurement above is kept because it is the argument, and because a project that publishes the numbers that killed its own biggest feature has earned the ones it kept. It is a snapshot of a date, not a live figure — nothing on this page can re-derive it, and that is stated rather than hidden.

The structural argument underneath it. An EVM contract can call getReserves() on the pool it cares about. A Kaspa L1 KIP-17 covenant cannot: it introspects only the transaction that spends it. So an oracle is convenient on an EVM L2 and the only mechanism on Kaspa L1 — and 58 feeds an EVM contract never needed an oracle for were not worth the count they added to the headline.

The depth-formula caveat, because the two numbers are not comparable. The L2 figure used the buy-side form with the 30 bps fee divided back in (factor 0.04895572); the L1 figure uses the sell-side honest form with no fee term (factor 0.04653741), capped at the live reserve. An L1 move_10pct_usd reads 4.94% below its old L2 counterpart on an identical reserve — enough to flip thin on a pool sitting near the $250 bar. Do not compare a figure from this page to a live one without that offset.

What went out of the wire with the tier: the krc20-l2 kind, pool_age_s, venues[], peg_ok, and the envelope’s peg block. peg_ok is still parsed by the API verification clients — their verify logic rejects peg_ok == false — so that check is now permanently inert rather than removed, and an old client keeps working unchanged. Do not add it to new code.

2026-08-24kaspulse/cov/v2, the bound covenant signature, shipped

Replaces the domain withdrawn on 2026-07-27. The preimage binds pair, mantissa, exponent, round and timestamp, so a signature for one pair can no longer be replayed against another. The browser and API verification clients rebuild the preimage from the feed’s own fields and demand the published bytes back byte-for-byte, rather than parsing what the server sent.

The signed-message specification, §8.0b, describes the bound encoding. Signature validity does not itself enforce freshness or authorize a beneficiary; those are separate consumer requirements.

2026-07-27The unbound covenant signature was WITHDRAWN

The hosted oracle’s covenant.signatures block signed blake2b(price_bytes) — a bare integer with no pair, no exponent and no round in it. One feed’s signature was therefore valid for any other feed at the same numeric value, and a gate written against it could be unlocked by a price that was never quoted for the pair it gated.

It was withdrawn rather than patched in place: for the four weeks between 2026-07-27 and 2026-08-24 the hosted oracle published no covenant attestation at all, and the only covenant encodings still signed were explicitly labelled test attestations, not hosted committee statements.

The hole became a regression test: a 24-case suite exercises Kaspa’s real script engine, and a valid committee signature for another pair — or the same pair at another exponent — is rejected by L1 script.

Spec: §8.0 (withdrawn) and §8.0b (replacement). Bond record: widened from 24 to 32 bytes on the same day, with a new domain-separated pair id.

The kind string has moved twice — match on a set, never inline

WhenValueWhat happened
before the L1 tier"krc20"the EVM pool feeds
the day the L1 tier landed"krc20-l2"renamed alongside the new "kcc20-pool"; every consumer comparing kind inline stopped matching, in silence
2026-08-24deletedremoved with the tier it named

A consumer that still filters for "krc20-l2" now matches nothing, which is the intended failure mode: it matches nothing loudly rather than pricing something wrong quietly. Two kinds ship today — "major" and "kcc20-pool".

Centralize kind handling in your application, and fail visibly on unknown values. KCC20. stays a reserved symbol prefix even though the tier that motivated the reservation is gone: a ticker-shaped pair can never collide with a covenant-shaped one.

Guidance for consumers: API reference.

Standing counts that are NOT on this page, on purpose

Current counts come from /v1/feeds and the full /v1/feed census, rather than being hard-coded as launch claims:

  • how many L1 markets are priced, and how many are refused
  • the median move_10pct_usd and which markets clear the $250 bar
  • the spot / last_verified_state split (it was 3 of 7 in mid-August, 1 of 7 on 2026-08-24 and 6 of 7 a few hours later the same day — a standing count here would have been wrong within hours)
  • how many priced tokens publish a ticker

A hand-typed launch figure is false within a week, and on a product whose whole brand is honesty that is the only failure that actually costs anything.

The dated census of the full kascov index — 93 mainnet markets, exactly one of which has ever claimed a ticker — is not computable from kaspulse’s own wire, so it lives here — dated 2026-08-24, in this changelog — not on a live page that cannot recompute it.