Methodology library
A methodology version is immutable once registered: its SHA-256 content hash is taken over the exact bytes of the document, and every composition and observation references the version under which it was produced. The hash is the verification mechanism — anyone holding the document can recompute it.
Currently registered — live from the registry
- Index
- PHIL10
- Version
- 1.5.0
- Content hash (SHA-256)
c258381be622c6079695fe0f58580200b5dd66df68428c4c45f153064875a27c
Version catalogue
| Version | Effective | Document | Change |
|---|---|---|---|
| 1.5.0 | 2026-08-10 | PHIL10 — Index Methodology sha256 c258381be622c6079695fe0f58580200b5dd66df68428c4c45f153064875a27c Read the document (49 KB)# PHIL10 — Index Methodology
**Index:** The Philidor Prime Yield Index
**Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD
**Methodology version:** 1.5.0
**Administrator:** Philidor Labs
Renamed in this version from "The Philidor Onchain Dollar Yield Index 10" (§17).
The code `PHIL10` and the identifier `phil10` are unchanged. Signed artefacts
bind to the identifier, not to either name, so the rename cannot orphan or
invalidate any existing evidence: a close signed before this version and one
signed after it identify the same index by the same value.
---
## 0. Status of this document and of the index
**PHIL10 is not an official benchmark and has no official inception date.** This
document governs a **public preliminary period**: the engine calculates a daily
level from real on-chain data, on a real schedule, under real fail-closed rules,
and every observation it produces carries one of the preliminary-period statuses
enumerated in §11.1 — never `official`. The levels, the rate,
the constituents, the census and this document are now publicly visible; no
product may track it, and the level series is not a track record.
This version changes what is _visible_. It changes nothing about what is
_claimed_. Every caveat below stood in the private phase and stands now.
Three things follow, and they are stated here because a rulebook that overclaims
is worse than none:
1. **Official inception is a separate, later act.** It requires a base date, a
base value of 100.00, a public preliminary period, and the governance
apparatus in §14 actually operating. Until then the series is a systems
artefact, not a benchmark. This version starts the preliminary period; it
does not end it, and it does not begin inception.
2. **No external methodology review has been performed.** The founders decided
on 2026-07-22 to hold the external reviewer seat open until the right person
is found rather than fill it for form's sake. Until that review exists, the
compensating controls are: this document published in full, the dual-engine
reconciliation of §9.4, the signed evidence of §9.5, and the honest
limitations of §16.
3. **Visibility is not publication.** In the data model an observation's
`publication_state` remains `released_private` throughout this period. That
field records whether an observation has been _officially published_ — it has
not — and it does not track whether a level is readable on a web page. The
two are separate, and §11 states the consequence: nothing on a public surface
may be presented as `official` while this version governs.
This document is versioned and content-hashed. The hash of the exact bytes of
this file is recorded in `index_methodology_versions.content_hash`, and every
composition and observation references the methodology version under which it
was produced.
---
## 1. Objective
PHIL10 is a rules-based, total-return index designed to measure a diversified
set of risk-qualified, implementation-eligible USD-denominated onchain yield
strategies.
It answers one question: _what does a disciplined dollar allocator actually earn
across the onchain venues that pass a real risk screen and can genuinely be
entered and exited?_
It is deliberately **not** a market-coverage index. Breadth is not the goal;
qualification is. Names beyond the constituent count (§5.1) are excluded on
purpose, and the published bench (§7.4) states exactly which rule excluded each
one.
---
## 2. Definitions
| Term | Meaning in this document |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. |
| **Close** | The daily calculation producing one level for one value date. "Official" is a reserved status this document does not yet confer (§0.3, §11.1). |
| **Constituent** | A vault included in the composition governing a value date. |
| **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. |
| **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). |
| **NAV per share** | The adapter-class per-unit value read on-chain at the pinned close block (§9.1): `convertToAssets(1 share)` for ERC-4626 vaults; the pool's normalized income per scaled aToken unit for Aave v3 (v1.4.0). |
| **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. |
| **Observation** | One recorded (index, value date, revision) row with a level and a status. "Recorded", not "published": publication in the §11.1 sense begins at inception. |
| **Collection** | One complete run of the input collector, identified by a collection id. |
---
## 3. Universe
A tracked vault is in the candidate universe if **all** of the following hold.
Every exclusion carries a machine-readable reason, so the census can state why a
name is out without a human re-deriving it.
1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`.
2. **Single-asset exposure.** A vault whose asset components list more than one
asset (e.g. USDC/WETH) is excluded — it is not a dollar vault.
3. **Active and not shut down.**
4. **Chain is not held out.** Held-out chain ids are enumerated in code and
currently comprise chain `9745`.
5. **The asset address is known.** Identity is (address, chain) everywhere
downstream — FX feeds, adapters, caps. A candidate without an asset address
cannot be carried honestly, so it is excluded rather than symbol-matched.
**Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not
merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS,
FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others
enumerated in code. The list exists so the exclusion is reviewable, and so a new
synthetic that slips past canonicalization is still caught by name.
**Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to
`circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and
is treated as a distinct asset that nonetheless consumes the Tether issuer cap.
---
## 4. Eligibility
A universe member must additionally pass **every** gate below. Order affects
only which reason is reported first.
| Gate | Threshold |
| ------------------------- | ---------------------------------------------------------------------------- |
| Risk vectors readable | Required — see fail-closed rule |
| Hard-fail flag | Must be absent |
| Depeg presumptive removal | Must be absent |
| Incident clamp | Must be absent |
| All-accruing | Required (v1 universe pays no distributions) |
| Reviewed | Required |
| Philidor risk score | ≥ **8.0** (Prime) |
| Vault TVL | ≥ **$5,000,000** |
| Vault age | ≥ **90 days** |
| Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** |
| Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** |
| Stressed clip | ≤ **20%** of vault TVL |
| FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain |
The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a
vault whose deposit asset cannot reach a price quorum on its chain is not priced
conservatively, it cannot be priced **at all**, and including it would stop the
index rather than degrade it. Independence is counted by oracle _family_, not by
contract: two feeds from the same provider are one source.
### 4.1 The fail-closed rule
**"We could not measure it" and "it passed" must never produce the same
outcome.** A candidate whose liquidity test could not be executed, or whose risk
vectors could not be read, is **ineligible** — it is never waved through. These
are reported as distinct reasons (`liquidity_test_unavailable`,
`risk_vectors_unavailable`) so the census can tell an unmeasurable name apart
from an illiquid one.
**All-accruing evidence (v1.1.0).** The all-accruing gate (§4) is evidenced by
the ingestion pipeline's reward observations. Because an empty reward set is
only informative when the pipeline demonstrably observes rewards for that
protocol, a protocol with no recorded reward stream is normally _unverifiable_
— excluded, not passed. One documented exception exists: a **mechanism
attestation**, a reviewed and provenance-carrying claim that the protocol's
vault design structurally cannot distribute value outside NAV (recorded in
code as `ACCRUAL_MECHANISM_ATTESTATIONS`). Currently attested (v1.4.0):
- **Spark/Sky Savings tokens**, whose yield accrues exclusively through the
Savings Rate raising `convertToAssets`; reviewed 2026-08-03.
- **Aave v3 aTokens**, which accrue depositor value exclusively through the
pool liquidity index raising `balanceOf` (read as the pool's
`getReserveNormalizedIncome` — §9.1); the aToken contract itself exposes no
distribution or claim mechanism. External Aave incentives
(incentives-controller and Merit campaigns) are distributed by separate
contracts, and the platform's Aave protocol adapter records them as reward
streams when they exist — a recorded stream still fails the gate as
`external_rewards` regardless of this attestation, which covers only the
missing pipeline-observability signal. Reviewed 2026-08-04.
An attestation substitutes only for
the missing pipeline-observability signal. It never outranks a recorded
reward stream, never bypasses evidence freshness, and never bypasses the
`apr_net = base_apr + Σ rewards` decomposition cross-check — an attested
protocol that starts paying incentives is caught by either surviving
detector.
### 4.2 What the liquidity test measures, and what it assumes
Stated plainly because the boundary is real:
- **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both
clip sizes, read on-chain at a pinned block.
- **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which
folds in the vault's currently available liquidity.
- **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an
underlying position unwinds, so tier-2 capacity is evaluated against total
assets, which **assumes an orderly 7-day unwind**. The assumption is recorded
in the signed evidence for every candidate so a reader sees it rather than
infers it.
This is a known limitation, restated in §16, and a live founder decision: either
accept the orderly-unwind assumption or require real unwind evidence and exclude
names that cannot supply it.
**Aave v3 withdrawability (v1.4.0).** An Aave v3 reserve has no
`previewWithdraw`/`maxWithdraw` surface, so its probe measures the mechanism it
actually has, still at a pinned block and still with no default-true path:
- **Capacity** is `min(probe holder's aToken balance, the reserve's available
liquidity)` — the underlying actually sitting in the aToken contract — and
both liquidity tiers gate on that figure. Available liquidity is
instantaneous; a 7-day orderly window can only replenish it (borrower
repayments, new supply), so gating tier 2 on the instantaneous figure is
conservative, and that assumption is recorded in the evidence.
- **Executability, not just balances.** Balances alone can record passes for
withdrawals that would revert, so the probe additionally requires the
reserve's configuration to show **active and unpaused** (a frozen reserve
blocks new supply but not withdrawal, so frozen alone does not fail it),
and requires a **debt-free probe holder**: a collateralized borrower's
withdrawal is bounded by health-factor math the probe does not model, so a
holder carrying any debt is an unmeasurable proxy, not a passing one.
- **Exit cost is zero by mechanism**, conditional on the above: withdrawal is
1:1 in the underlying when available liquidity suffices — there is no
share/asset conversion and no pool-level fee — and the evidence records it
as such rather than measuring it through a preview that does not exist on
this ABI.
- The **stressed clip** is evaluated against the reserve's total aToken
supply, mirroring the ERC-4626 total-assets basis.
As on the ERC-4626 path, a candidate with no configured probe holder is
unmeasurable and therefore ineligible.
---
## 5. Selection
1. Rank all eligible candidates by the **total, data-driven ordering**: risk
score descending, then vault age descending, then TVL descending, then
ref_id ascending. Every tie-break is deterministic — a selection that could
depend on map iteration order could not be reproduced, which would make the
evidence chain worthless.
2. Take the top **N** (§5.1).
3. **Incumbency buffer.** An incumbent constituent is displaced only if the
challenger beats it by **more than 0.2** of a risk score point **and** by
**more than 3** rank places — both, strictly; clearing one alone retains
the incumbent, and a challenger at exactly 0.2 points or exactly 3 ranks
has not cleared it. (Corrected in v1.2.0: earlier versions of this document
said "or", describing a rule the engine has never implemented — turnover
must be clearly earned on both measures.) This suppresses churn from noise.
The buffer is bypassed by extraordinary events (§12) — a hard-failed name
leaves immediately.
If fewer than N eligible names exist, the reconstitution is **infeasible** and
reports why. PHIL10 does not publish an N-name index with N−1 names, and does
not lower a gate to reach the number.
### 5.1 Constituent count (v1.2.0)
**N = 5 at glidepath start. The target remains 10** — it is the index's name
and its destination — and each step back toward it is a methodology version.
This is the census speaking, not a preference. The first production census
(2026-08-03) measured **5** names clearing every gate. The gap to 10 is not a
tuning problem: at that census the calculation engine priced ERC-4626 vaults
only, which excluded rebasing money-market receipts (Aave aTokens, Compound
Comet) regardless of their quality; reward-observability and
executed-liquidity evidence exclude what cannot yet be measured; and the next
nearest name enters by vault age in September 2026. As of v1.4.0 the engine
additionally prices **Aave v3 aTokens** through a dedicated adapter class
(§9.1) with a matching liquidity probe (§4.2) and accrual attestation (§4.1);
Compound Comet remains unsupported (its supply index only advances on accrual,
and honest pinned-block support would require present-value rate math the
engine does not approximate). The alternatives to reducing N were all worse:
relaxing a gate (forbidden — §4.1), widening the universe into synthetic
dollars (§3 excludes them by name, deliberately), or publishing nothing for
months while a five-name book of measured, risk-qualified names sits idle.
What a smaller N costs, stated plainly: less diversification per name (each
constituent is 20% at target rather than 10%), and caps that bind harder
(three same-protocol names are 60% of a five-name book). The §6.1 levels were
re-checked against N = 5 on the measured census — the curator cap binds first
(two same-curator names = 40% against 35%) and the waterfall's deterministic
redistribution handles it. The count rises — 6, 7, … 10 — as names age in,
measurement coverage widens, and scores move; each increase is a version bump
justified by census evidence, exactly like a cap change.
**When the count steps (v1.4.0).** Eligible-universe growth from a newly
measurable adapter class — such as the Aave v3 class this version adds —
never changes N by itself: **N is fixed until a methodology version changes
it**, and each increase is a version bump justified by census evidence,
exactly like a cap change. Membership within the fixed N can change at any
**reconstitution** — scheduled or extraordinary (§7.2) — because both invoke
the same selection run; between reconstitutions the composition is fixed and
weights drift with performance (§6.2). A newly measurable name therefore
enters exactly the way any other challenger does: through every gate, at a
reconstitution, with the incumbency buffer applied to scheduled runs (an
extraordinary reconstitution triggered by a §7.2 gate breach deliberately
bypasses it, as §7.2 records).
---
## 6. Weighting
**Equal weight**: each constituent's target is 1/N of the index, N per §5.1
(5 at glidepath start, target 10).
The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75%
safer than an 8.0, and score-weighting would make one estimate do two jobs, so a
small scoring error would move both membership and capital.
### 6.1 Look-through caps
Applied to the target weights by a deterministic cap-and-redistribution
waterfall, on four dimensions:
| Dimension | Cap |
| --------- | ---- |
| Protocol | 60% |
| Issuer | 100% |
| Curator | 35% |
| Chain | 70% |
Caps bind on the **look-through** dimension, not the vault name: two vaults on
one protocol consume that protocol's cap jointly. Where a cap binds, weight is
redistributed deterministically to uncapped names; the binding dimensions are
recorded on the selection run. If the cap system cannot be satisfied, the
reconstitution is infeasible and says so — caps are not quietly relaxed to force
a result.
**A null look-through key is membership in no group (v1.1.0).** A
protocol-native vault (Aave, Spark, Compound, Yearn) has no curator: it belongs
to no curator group and consumes no curator cap, in the trimming waterfall and
in every verification of it alike. This is not a relaxation of the fail-closed
rule — "there is no curator" is a measured fact about the vault's design, while
"the curator is unknown where one should exist" is missing metadata, and
missing metadata is an _eligibility_ exclusion decided before the waterfall
ever runs (a curated-platform vault with no curator attribution is excluded as
`curator_attribution_unavailable`). The same semantics apply to every cap
dimension.
**Cap levels are census-derived (v1.1.0).** The v1.0.0 levels
(35/50/35/70) were set before any census had run against production. The first
real census (2026-08-03, value date 2026-08-02) measured an eligible book that
no 10-name equal-weight composition can satisfy under them: the measurable
universe is Spark Savings and curated Morpho vaults in roughly equal number
(each ~50% of a ten-name book against a 35% protocol cap), and 90–100%
Circle-issued deposits (against a 50% issuer cap). A cap that admits no
composition at all protects nothing. The v1.1.0 levels are the tightest caps
the measured census satisfies with modest drift headroom: protocol 60%, issuer
100% (non-binding at glidepath start, stated plainly rather than pretended
at), curator and chain unchanged. These remain a **glidepath**: they
re-tighten as the eligible universe widens. Nothing re-tightens by itself — a
100% cap constrains nothing (weights always sum to exactly 100%, so the
waterfall excludes such a dimension outright rather than letting rounding
residue bind it) until a human lowers it, and like every cap change that takes
a new methodology version with its own hash. Re-tightening the issuer cap is
the first scheduled glidepath step once measurable non-Circle deposits exist,
and each quarterly census is the standing occasion to take it.
### 6.2 Weight drift
Between reconstitutions, weights **drift with performance**. They are not reset
to target daily. Resetting daily would silently rebalance the index every day
and publish a wrong level from day two onward — and both calculation engines
would agree on it, because they would share the same malformed input.
---
## 7. Reconstitution
### 7.1 Schedule
Scheduled reconstitutions are quarterly. A new composition is effective from a
stated value date and governs closes **after** that date (§8.3).
### 7.2 Extraordinary reconstitution
Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of
Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not
apply. An index deletion is not a claim that a tracker could have exited at that
price — see §16.
### 7.3 Evidence
Every reconstitution records the full census: every candidate considered, every
eligibility verdict with its reason, the ranking, the caps that bound, and the
resulting composition — hashed and signed.
### 7.4 The bench
The ranked eligible names that missed the cut are published with their rank.
"The next four names and exactly which rule keeps each one out" is part of the
product, not a byproduct.
---
## 8. Calculation
The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md`
(fixed-point representation, rounding, primitive operations, bounds). It governs
where it is more specific than this section.
### 8.1 Constituent return
For constituent _i_ over the interval ending at value date _t_:
```
r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1
```
`D` is distributions. The v1 universe is all-accruing, so **D = 0 by
construction** — yield accrues inside NAV per share. A vault that distributes is
ineligible (§4) precisely so this term cannot be silently wrong.
FX is a real measured price, not an assumed $1.00. A depeg therefore flows into
the index level mechanically, as a loss, rather than being invisible.
### 8.2 Index level
```
L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t)
```
Chain-linking is the definition, not an approximation. Opening weights are the
previous close's **drifted** weights (§6.2), never the composition targets —
except on the first close after a reconstitution took effect, which is what a
reconstitution means.
### 8.3 Reconstitution boundary
A composition effective for value date D applies from D's close **forward**. The
return _ending_ at D is computed under the **outgoing** composition; the new
targets open the next interval. Applying the incoming composition to D would
compute D's return over a constituent set that was not in force during it.
### 8.4 Gaps
If the previous accepted close is more than one day earlier, the interval is a
**multi-day return**, correctly labelled as such — never a silently mislabelled
one-day return. A multi-day interval may not span a reconstitution boundary: if
it would, the close defers rather than applying weights retroactively to days
they did not govern.
### 8.5 Back-calculated history (v1.3.0)
Pre-inception history MAY be reconstructed, under rules that keep it honest:
1. **The current book is held fixed.** A back-calculation clones the initial
composition verbatim (reason `back_calc`) and reprices it at pinned,
finalized historical blocks. It is NEVER a point-in-time re-selection:
eligibility as of past dates is not reconstructible from recorded data
(the Phase 0 finding), and pretending otherwise would be hindsight dressed
as history.
2. **Same engine, same evidence.** Every reconstructed close runs the full
production pipeline — sealed manifest, both engines, zero-tolerance
reconciliation, signed exported evidence.
3. **Labeled, always.** Reconstructed observations carry
`history_class = back_calculated` and that display status, regardless of
any other state. They are never presented as live, and the publication
target (lateness) does not apply to them.
4. **Scale-continuous, never restating.** The reconstructed segment is
anchored so that its final level times the TRUE boundary return (computed
target-weighted from the segment-end collection and the first live close's
sealed inputs) equals the live base, to within a stated rounding residual.
The live chain — including the first live close's inception zero return —
is never modified; acceptance is terminal.
5. **PPR basis disclosure.** A PPR fixing whose window includes reconstructed
observations states so (`basis` on the fixing): the rate is real arithmetic
over a partially reconstructed series, and the reader decides what that is
worth. Endpoints are still never substituted.
### 8.6 Precision
Internal arithmetic is scaled integer at 8 decimal places with half-even
rounding at defined points only. Published levels are stated at 2 decimal
places. Value date, calculation timestamp and publication timestamp are distinct
fields and are never conflated.
---
## 9. Data, provenance and verification
### 9.1 NAV
NAV is read on-chain at a **pinned block** per chain, after that chain's
finality rule is satisfied, by the vault's registered **adapter class**
(v1.4.0). Two classes exist; each defines "one share" so that the return
ratio `NAV_t / NAV_{t-1}` measures the growth in **asset value per held
unit**: for an ERC-4626 vault the holder's share count is constant and each
share's asset-equivalent value grows by the ratio; for an aToken the
holder's `balanceOf` itself grows by the ratio **absent holder flows**
(deposits, withdrawals and transfers move scaled principal and are not
return). The normative arithmetic is
`packages/shared/src/indices/ARITHMETIC.md` §NAV.
**ERC-4626** — `convertToAssets(1 share)`. Before the read is accepted:
`asset()` must still bind to the expected deposit asset; `totalSupply()` must be
non-zero; the resulting NAV must be plausible; and a move beyond **500 bps**
from the previous accepted NAV is **rejected**, not clamped — a clamped absurd
input produces a plausible wrong number, the failure a benchmark can least
afford.
**Aave v3 aTokens** — a rebasing receipt: holder balance = scaled balance ×
the pool's liquidity index, so NAV is defined **per scaled unit** and read as
the pool's `getReserveNormalizedIncome(underlying)`, a ray (27-decimal) value
that the pool computes with linear accrual to the queried block — which is
what makes a pinned-block read correct without replicating rate math off-chain.
The ray is normalized to the internal 8-decimal scale with half-even rounding.
Before the read is accepted, the **identity chain is re-asserted on every
read**: `UNDERLYING_ASSET_ADDRESS()` must bind to the expected deposit asset;
`totalSupply()` must be non-zero; `POOL()` must equal the pool the census probe
verified and froze at registration — an adapter registered **without** that
pool anchor is refused outright, never priced on the self-reported pool — and
the pool's reserve data for the underlying must name this aToken back. A pool
swap or proxy re-point after registration therefore fails closed instead of
feeding a plausible fake income stream. Additionally, a reserve carrying
**material recognized bad debt** fails the reading closed — nominal balance
growth on such a reserve is not realizable. Materiality (v1.4.1) is bounded
relative to the reserve: a recognized deficit **strictly greater than 0.1
basis point (1/1,000,000) of total aToken supply** — both figures
underlying-denominated, so the ratio is unit-free — fails closed; a deficit
at or below the bound is **de minimis** (dust-scale residue of resolved
liquidations, orders of magnitude beneath the index's own 8-decimal
representation and daily-return scale), and the reading proceeds on the
nominal basis with the exact deficit recorded as a warning in the
collection evidence. The v1.4.0 rule was absolute (any deficit > 0); the
first live close under it demonstrated that a long-lived reserve routinely
carries sub-dollar recognized dust, which would defer the close
indefinitely without representing any measurable impairment. **Any**
failure to read the deficit getter still fails closed at NAV time.
Deficit-getter support is for that reason a **registration requirement**: the
census probe refuses pools whose getter does not respond, and pre-3.3
deployments without it are out of scope. The plausibility bound and the
500 bps anomaly rejection are shared with the ERC-4626 class verbatim.
Share and asset decimals are **probed on-chain at registration** and persisted.
They are never defaulted: a vault without probed conformance is not priced, the
collection is therefore incomplete, and the close defers. (For the Aave class
the "share" unit is definitionally the ray scale, recorded at registration
rather than probed; the underlying's decimals are probed like any other.)
### 9.2 FX
Push oracles only, from the families `chainlink`, `chronicle`, `redstone`,
`api3`. The registry is keyed by **token address + chain**, never by symbol —
symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark.
The published FX is the **median of the responsive quorum**. A quote more than
200 bps from that median is **flagged and still counted** — it is not discarded.
That is deliberate, and worth stating plainly because the intuitive rule is the
opposite. Discarding a quote requires deciding it is wrong, and the median is
already robust to a single bad source without that decision. More importantly,
exclusion would make aggregation depend on a _prior pass's_ labels: replaying the
stored evidence for a past close could then produce a different number from the
one published, which would make the evidence package unverifiable. Flagging
records the disagreement in the evidence without letting it change the
arithmetic.
Independence is counted by **oracle family**, and a single feed address may not
be registered under more than one family — quorum is a claim about independent
sources, not about rows.
**A known dependency, stated because it is invisible otherwise.** Chronicle's
mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller
except a short allowlist, which includes the zero address. PHIL10 reads them as
an off-chain indexer via `eth_call` with no `from`, which defaults to the zero
address, so the reads succeed — but that permission is Chronicle's to revoke. If
it were revoked, those quotes would begin erroring rather than returning a wrong
number, the affected assets would fall from three responsive sources to two, and
pricing would continue in a recorded degraded state. The failure mode is
therefore visible and safe, but the dependency is real and is not something
PHIL10 controls.
Losing quorum does not produce a price: it produces a recorded degraded state
with a reason. An asset with fewer than three independent feeds is a founder
decision, not something the collector works around: such an asset is excluded
from the universe by the FX-quorum gate (§4) rather than silently priced.
### 9.3 Collection coherence
Every input row is stamped with a collection id. A completeness sentinel is
written **last**, and only when every constituent produced both a NAV and a
median. A crashed or partial collection leaves no sentinel and is never
consumed — the close reads the last complete collection, or defers.
### 9.4 Dual-engine reconciliation
Every close is computed twice: a primary scaled-integer engine in TypeScript and
an independent engine in PostgreSQL `numeric`, over the **same sealed inputs**
but on a different arithmetic substrate. Agreement is required at **zero
tolerance** on the level, the daily return, each constituent return and each
close weight. Disagreement **blocks publication**; it does not average, pick a
side, or warn.
### 9.5 Evidence
Every close emits a signed evidence package: the sealed inputs, both engines'
results, the reconciliation, the governing composition and methodology version,
engine versions and hashes. Signatures are Ed25519; the public half of every
signing key is registered in an append-only registry before use, so historical
signatures remain verifiable across key rotation.
### 9.6 Append-only
Observations, inputs, runs and evidence are **insert-only**, enforced by
database triggers, including protection against TRUNCATE. A correction is a new
revision plus a notice (§13). History is never edited.
---
## 10. Staleness ladder and statuses
| Input age at close | Effect |
| ------------------ | --------------------------------------------------------- |
| ≤ 6h | Normal |
| > 6h | Constituent flagged; close proceeds |
| > 48h | Close proceeds, status records calculation on stale input |
| > 72h | **Close is `not_calculated`** |
A single constituent past 72h makes the whole close `not_calculated`.
Constituents are **never dropped and renormalized to rescue a close** — that
would silently change the composition on precisely the days the data is worst.
A carried-forward annualized rate is never accrued.
**Status vocabulary** (fixed; these exact words appear in the API):
`preliminary`, `official`, `revised`, `delayed`, `insufficient_data`,
`not_calculated`, `back_calculated`.
An honest gap is **permanent**: once a later close has been accepted, a skipped
date is not retroactively filled, because doing so would break the internal
chaining of an already-signed series.
---
## 11. Publication
Closes are calculated after the value date's close instant and after chain
finality. The target release time is 16:30 UTC. A late close is released late
and labelled, never backdated. A close that cannot be computed is recorded
with the reason — silence is not a permitted outcome, and a dead-man's watchdog
alerts if a value date passes with no observation.
### 11.1 The public preliminary period (v1.5.0)
**Where.** Publicly visible means the index's own pages, without credential.
The HTTP API stays credentialed in this version: `/v1/indices/*` and
`/v1/rates/*` continue to require a bearer, and an anonymous request to them is
refused. This document does not promise an anonymous API, and no surface may
imply one.
Publicly visible, without credential, on those pages:
- the index level series, each observation carrying its own status. The
statuses reachable in this period are `back_calculated`, `preliminary`,
`delayed`, `revised` (the observation was restated through a correction
batch, §13) and `not_calculated` (the close could not be computed and the
reason is recorded, §8.4). **Never `official`** — that status is reserved for
observations released after inception, and no surface may display it while
this version governs;
- PPR-USD — the **Philidor Prime Yield Rate**, the index's annualized reference
yield. It is a realized return statistic derived from PHIL10, not a lending
rate and not a rate any borrower is quoted. The published fixing record is
authoritative: a fixing the registry withholds (superseded, pending its
correction batch) is shown as withheld and **never replaced by a recomputed
number**, and each fixing discloses its basis under §8.5;
- the current composition, its target weights, and the drift of each
constituent's current weight from that target;
- the eligibility census behind that composition, including the bench and each
exclusion reason, with the content hash of its evidence. The census is served
with that hash, not with a signature: a reader may verify integrity against
the hash, and the signature over the underlying evidence is furnished on
request with the evidence package;
- every registered methodology version — the document bytes themselves, not
only their metadata — each with the SHA-256 a reader can recompute over
exactly those bytes;
- notices (§13) and governance (§14).
Available on request, not anonymously: the per-close signed evidence packages,
the dual-engine reconciliation record, collection quality detail, and the
signatures over them. These are withheld for load and commercial reasons, not
because they are less certain — they are the strongest evidence the index
produces, and §0's compensating controls depend on them existing and being
auditable. They are furnished to any counterparty who asks.
Two rules bind this period:
1. **No observation may be presented as `official`, anywhere, under any
status derivation.** `official` is reserved for observations released after
inception, and inception has not occurred.
2. **A public page may not state less than this document states about the
numbers it shows.** Concretely: every level carries its status and its value
date, every rate carries its window and basis, and every page carries the
regulatory status of §15 and a route to the limitations of §16 and to this
document in full. A page showing a level without its status, or a rate
without its basis, is not a permitted rendering.
The period ends only at official inception, which requires everything in §0.1.
It has no scheduled end date in this version.
---
## 12. Depeg ladder
Evaluated on the deposit asset against a two-source-minimum quorum:
| Condition | Action |
| --------------------------- | -------------------------------------------- |
| < $0.985 for 4 hours | Review flagged |
| < $0.97 for 15 minutes | Extraordinary review flagged |
| < $0.95, quorum-confirmed | **Presumptive removal** |
| < $0.95, single source only | Extraordinary flagged (removal needs quorum) |
Flags annotate a close; they never block it. Severity is **monotonic within an
open episode** — it can only rise. It clears only through the quorum-guarded
recovery exit that closes the episode; a single low-confidence tick can never
downgrade a confirmed removal and re-admit a still-depegged vault.
A depeg is also visible in the level itself, because FX is measured (§8.1).
---
## 13. Corrections and restatement
An error is corrected by **new revisions plus a numbered public notice** stating
what changed, why, which value dates are affected and what the levels were
before and after. Prior revisions remain queryable forever. The methodology
version and composition that governed each revision remain attached to it.
---
## 14. Governance
- **Index committee:** two founders. The external seat is deliberately **open**
(see §0) and will be filled when the right person is found rather than for
appearance.
- **Methodology changes** are new versions with new hashes. The index is public
as of this version, so the consultation obligation is now **live, not
conditional**: a non-emergency methodology change is announced by notice and
carries a public consultation period before it takes effect. An emergency
change may take effect immediately and is announced by notice with its
justification. This version is itself exempt, being the change that opens the
period, and is announced by notice.
- **Conflicts:** Philidor operates no product tracking PHIL10, and none is
planned for v1. Risk-assessment commercial relationships with constituents'
operators, where they exist, are disclosed as a category. The controlling
rule, which admits no exception: **money can buy coverage, custom products and
calculation services; it can never buy a risk score or a seat in a standard
index.**
- **Cessation:** if PHIL10 stops being calculated, that is announced with a
notice and the historical series remains published and verifiable.
---
## 15. Regulatory status
PHIL10 is publicly visible but not officially published (§11.1), licensed to no
one, and tracked by no product. No regulatory-status claim is made in this
version, and none may be made on any surface presenting the index: PHIL10 is not
administered under any benchmark regulation, and no representation is made that
it constitutes a benchmark within the meaning of any such regulation.
A counsel-reviewed benchmark statement remains a prerequisite for public
inception. It is not a prerequisite for this document or for the preliminary
period it governs, because neither makes a benchmark claim.
Nothing here is investment advice. An index level is an informational
calculation over on-chain data; it is not a price at which any transaction could
have been executed.
---
## 16. Known limitations
Stated exactly, because a rulebook that hides them is not worth publishing:
1. **The universe is small and concentrated.** Five names at glidepath start
(§5.1), drawn from a single-digit eligible set dominated by two protocols.
Caps (§6.1) and the constituent count are both set at glidepath levels for
exactly this reason, and the binding dimensions are published per
reconstitution.
2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is
measured; the horizon is not observable on-chain.
3. **Index deletion is not tracker realizability.** An extraordinary
reconstitution removes a name from the index; it does not assert that a
holder could have exited at that price, or at all.
4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps
NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic
loss looks implausible, so the close defers rather than recording it. This is
deliberate fail-closed behaviour and an open founder decision: a crisis
confirmation path is required before PHIL10 can claim to measure a crisis.
5. **No external methodology review** (§0).
6. **No public track record.** The series is preliminary. It became publicly
visible in v1.5.0, which starts the elapsed public record at that date and
does not backdate it — visibility is not history. Elapsed operating time
cannot be simulated or shortened.
7. **Back-calculated history is a fixed-book reconstruction, not point-in-time
history** (§8.5, v1.3.0). Point-in-time eligibility is not reconstructable,
so the reconstruction holds the current book fixed and says so on every
observation. Selection history before inception does not exist and is not
claimed.
---
## 17. Version history
| Version | Date | Change |
| ------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. |
| 1.1.0 | 2026-08-03 | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key = no group, with curated-platform attribution failures excluded at eligibility; mechanism-attestation evidence path for the all-accruing gate (Spark). |
| 1.2.0 | 2026-08-03 | Constituent count N = 5 at glidepath start (census: 5 names clear every gate; target remains 10, each step back is a version — §5.1). |
| 1.3.0 | 2026-08-03 | Back-calculated history rules (§8.5): fixed-book reconstruction at pinned blocks, full pipeline + evidence, always labeled, scale-continuous anchoring, PPR basis disclosure. |
| 1.4.0 | 2026-08-04 | Aave v3 aToken adapter class: scaled-unit NAV from pool normalized income, identity anchoring, deficit fail-closed (§9.1); Aave withdrawability probe (§4.2); Aave accrual attestation (§4.1); count steps only at a reconstitution (§5.1). |
| 1.4.1 | 2026-08-04 | Deficit materiality bound (§9.1): recognized reserve deficit fails closed only above 0.1 bp of total aToken supply; at or below the bound the reading proceeds on the nominal basis with the deficit recorded as a warning. Prompted by the first live Aave close: mainnet aEthUSDT carries a sub-dollar recognized dust deficit that wedged the close under the absolute v1.4.0 rule. |
| 1.5.0 | 2026-08-10 | Public preliminary period opens (§0, §11.1): levels, rate, constituents, census and methodology become publicly visible; signed evidence remains furnished on request. Renamed from "The Philidor Onchain Dollar Yield Index 10" to "The Philidor Prime Yield Index"; PPR-USD displayed as the Philidor Prime Yield Rate. Codes `PHIL10` and `PPR-USD`, the identifier `phil10` and all signed artefacts unchanged. Visibility is not publication: `publication_state` stays `released_private` and no observation may be presented as `official` (§0.3, §11.1). Consultation obligation becomes live (§14). No benchmark claim, no inception, no base date. |
| Public preliminary period opens (§0, §11.1): levels, rate, constituents, census and methodology become publicly visible, signed evidence furnished on request. Renamed to the Philidor Prime Yield Index; PPR-USD displayed as the Philidor Prime Yield Rate. Visibility is not publication — no observation is official. No benchmark claim, no inception. |
| 1.4.1 | 2026-08-04 | PHIL10 — Index Methodology sha256 a10c84fb62fe565a747c00227e2ac5e671ef392cca350346db8ed0481d733e28 Read the document (41 KB)# PHIL10 — Index Methodology
**Index:** The Philidor Onchain Dollar Yield Index 10
**Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD
**Methodology version:** 1.4.1
**Administrator:** Philidor Labs
---
## 0. Status of this document and of the index
**PHIL10 is not an official benchmark and has no official inception date.** This
document governs a **private operational soak**: the engine calculates a daily
level from real on-chain data, on a real schedule, under real fail-closed rules,
and every live observation it produces carries the status `preliminary`
(reconstructed history carries `back_calculated` — §8.5). Nothing is
published publicly, no product may track it, and the level series is not a track
record.
Two things follow, and they are stated here because a rulebook that overclaims
is worse than none:
1. **Official inception is a separate, later act.** It requires a base date, a
base value of 100.00, a public preliminary period, and the governance
apparatus in §14 actually operating. Until then the series is a systems
artefact, not a benchmark.
2. **No external methodology review has been performed.** The founders decided
on 2026-07-22 to hold the external reviewer seat open until the right person
is found rather than fill it for form's sake. Until that review exists, the
compensating controls are: this document published in full, the dual-engine
reconciliation of §9.4, the signed evidence of §9.5, and the honest
limitations of §16.
This document is versioned and content-hashed. The hash of the exact bytes of
this file is recorded in `index_methodology_versions.content_hash`, and every
composition and observation references the methodology version under which it
was produced.
---
## 1. Objective
PHIL10 is a rules-based, total-return index designed to measure a diversified
set of risk-qualified, implementation-eligible USD-denominated onchain yield
strategies.
It answers one question: _what does a disciplined dollar allocator actually earn
across the onchain venues that pass a real risk screen and can genuinely be
entered and exited?_
It is deliberately **not** a market-coverage index. Breadth is not the goal;
qualification is. Names beyond the constituent count (§5.1) are excluded on
purpose, and the published bench (§7.4) states exactly which rule excluded each
one.
---
## 2. Definitions
| Term | Meaning in this document |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. |
| **Close** | The daily calculation producing one official level for one value date. |
| **Constituent** | A vault included in the composition governing a value date. |
| **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. |
| **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). |
| **NAV per share** | The adapter-class per-unit value read on-chain at the pinned close block (§9.1): `convertToAssets(1 share)` for ERC-4626 vaults; the pool's normalized income per scaled aToken unit for Aave v3 (v1.4.0). |
| **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. |
| **Observation** | One published (index, value date, revision) row with a level and a status. |
| **Collection** | One complete run of the input collector, identified by a collection id. |
---
## 3. Universe
A tracked vault is in the candidate universe if **all** of the following hold.
Every exclusion carries a machine-readable reason, so the census can state why a
name is out without a human re-deriving it.
1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`.
2. **Single-asset exposure.** A vault whose asset components list more than one
asset (e.g. USDC/WETH) is excluded — it is not a dollar vault.
3. **Active and not shut down.**
4. **Chain is not held out.** Held-out chain ids are enumerated in code and
currently comprise chain `9745`.
5. **The asset address is known.** Identity is (address, chain) everywhere
downstream — FX feeds, adapters, caps. A candidate without an asset address
cannot be carried honestly, so it is excluded rather than symbol-matched.
**Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not
merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS,
FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others
enumerated in code. The list exists so the exclusion is reviewable, and so a new
synthetic that slips past canonicalization is still caught by name.
**Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to
`circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and
is treated as a distinct asset that nonetheless consumes the Tether issuer cap.
---
## 4. Eligibility
A universe member must additionally pass **every** gate below. Order affects
only which reason is reported first.
| Gate | Threshold |
| ------------------------- | ---------------------------------------------------------------------------- |
| Risk vectors readable | Required — see fail-closed rule |
| Hard-fail flag | Must be absent |
| Depeg presumptive removal | Must be absent |
| Incident clamp | Must be absent |
| All-accruing | Required (v1 universe pays no distributions) |
| Reviewed | Required |
| Philidor risk score | ≥ **8.0** (Prime) |
| Vault TVL | ≥ **$5,000,000** |
| Vault age | ≥ **90 days** |
| Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** |
| Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** |
| Stressed clip | ≤ **20%** of vault TVL |
| FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain |
The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a
vault whose deposit asset cannot reach a price quorum on its chain is not priced
conservatively, it cannot be priced **at all**, and including it would stop the
index rather than degrade it. Independence is counted by oracle _family_, not by
contract: two feeds from the same provider are one source.
### 4.1 The fail-closed rule
**"We could not measure it" and "it passed" must never produce the same
outcome.** A candidate whose liquidity test could not be executed, or whose risk
vectors could not be read, is **ineligible** — it is never waved through. These
are reported as distinct reasons (`liquidity_test_unavailable`,
`risk_vectors_unavailable`) so the census can tell an unmeasurable name apart
from an illiquid one.
**All-accruing evidence (v1.1.0).** The all-accruing gate (§4) is evidenced by
the ingestion pipeline's reward observations. Because an empty reward set is
only informative when the pipeline demonstrably observes rewards for that
protocol, a protocol with no recorded reward stream is normally _unverifiable_
— excluded, not passed. One documented exception exists: a **mechanism
attestation**, a reviewed and provenance-carrying claim that the protocol's
vault design structurally cannot distribute value outside NAV (recorded in
code as `ACCRUAL_MECHANISM_ATTESTATIONS`). Currently attested (v1.4.0):
- **Spark/Sky Savings tokens**, whose yield accrues exclusively through the
Savings Rate raising `convertToAssets`; reviewed 2026-08-03.
- **Aave v3 aTokens**, which accrue depositor value exclusively through the
pool liquidity index raising `balanceOf` (read as the pool's
`getReserveNormalizedIncome` — §9.1); the aToken contract itself exposes no
distribution or claim mechanism. External Aave incentives
(incentives-controller and Merit campaigns) are distributed by separate
contracts, and the platform's Aave protocol adapter records them as reward
streams when they exist — a recorded stream still fails the gate as
`external_rewards` regardless of this attestation, which covers only the
missing pipeline-observability signal. Reviewed 2026-08-04.
An attestation substitutes only for
the missing pipeline-observability signal. It never outranks a recorded
reward stream, never bypasses evidence freshness, and never bypasses the
`apr_net = base_apr + Σ rewards` decomposition cross-check — an attested
protocol that starts paying incentives is caught by either surviving
detector.
### 4.2 What the liquidity test measures, and what it assumes
Stated plainly because the boundary is real:
- **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both
clip sizes, read on-chain at a pinned block.
- **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which
folds in the vault's currently available liquidity.
- **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an
underlying position unwinds, so tier-2 capacity is evaluated against total
assets, which **assumes an orderly 7-day unwind**. The assumption is recorded
in the signed evidence for every candidate so a reader sees it rather than
infers it.
This is a known limitation, restated in §16, and a live founder decision: either
accept the orderly-unwind assumption or require real unwind evidence and exclude
names that cannot supply it.
**Aave v3 withdrawability (v1.4.0).** An Aave v3 reserve has no
`previewWithdraw`/`maxWithdraw` surface, so its probe measures the mechanism it
actually has, still at a pinned block and still with no default-true path:
- **Capacity** is `min(probe holder's aToken balance, the reserve's available
liquidity)` — the underlying actually sitting in the aToken contract — and
both liquidity tiers gate on that figure. Available liquidity is
instantaneous; a 7-day orderly window can only replenish it (borrower
repayments, new supply), so gating tier 2 on the instantaneous figure is
conservative, and that assumption is recorded in the evidence.
- **Executability, not just balances.** Balances alone can record passes for
withdrawals that would revert, so the probe additionally requires the
reserve's configuration to show **active and unpaused** (a frozen reserve
blocks new supply but not withdrawal, so frozen alone does not fail it),
and requires a **debt-free probe holder**: a collateralized borrower's
withdrawal is bounded by health-factor math the probe does not model, so a
holder carrying any debt is an unmeasurable proxy, not a passing one.
- **Exit cost is zero by mechanism**, conditional on the above: withdrawal is
1:1 in the underlying when available liquidity suffices — there is no
share/asset conversion and no pool-level fee — and the evidence records it
as such rather than measuring it through a preview that does not exist on
this ABI.
- The **stressed clip** is evaluated against the reserve's total aToken
supply, mirroring the ERC-4626 total-assets basis.
As on the ERC-4626 path, a candidate with no configured probe holder is
unmeasurable and therefore ineligible.
---
## 5. Selection
1. Rank all eligible candidates by the **total, data-driven ordering**: risk
score descending, then vault age descending, then TVL descending, then
ref_id ascending. Every tie-break is deterministic — a selection that could
depend on map iteration order could not be reproduced, which would make the
evidence chain worthless.
2. Take the top **N** (§5.1).
3. **Incumbency buffer.** An incumbent constituent is displaced only if the
challenger beats it by **more than 0.2** of a risk score point **and** by
**more than 3** rank places — both, strictly; clearing one alone retains
the incumbent, and a challenger at exactly 0.2 points or exactly 3 ranks
has not cleared it. (Corrected in v1.2.0: earlier versions of this document
said "or", describing a rule the engine has never implemented — turnover
must be clearly earned on both measures.) This suppresses churn from noise.
The buffer is bypassed by extraordinary events (§12) — a hard-failed name
leaves immediately.
If fewer than N eligible names exist, the reconstitution is **infeasible** and
reports why. PHIL10 does not publish an N-name index with N−1 names, and does
not lower a gate to reach the number.
### 5.1 Constituent count (v1.2.0)
**N = 5 at glidepath start. The target remains 10** — it is the index's name
and its destination — and each step back toward it is a methodology version.
This is the census speaking, not a preference. The first production census
(2026-08-03) measured **5** names clearing every gate. The gap to 10 is not a
tuning problem: at that census the calculation engine priced ERC-4626 vaults
only, which excluded rebasing money-market receipts (Aave aTokens, Compound
Comet) regardless of their quality; reward-observability and
executed-liquidity evidence exclude what cannot yet be measured; and the next
nearest name enters by vault age in September 2026. As of v1.4.0 the engine
additionally prices **Aave v3 aTokens** through a dedicated adapter class
(§9.1) with a matching liquidity probe (§4.2) and accrual attestation (§4.1);
Compound Comet remains unsupported (its supply index only advances on accrual,
and honest pinned-block support would require present-value rate math the
engine does not approximate). The alternatives to reducing N were all worse:
relaxing a gate (forbidden — §4.1), widening the universe into synthetic
dollars (§3 excludes them by name, deliberately), or publishing nothing for
months while a five-name book of measured, risk-qualified names sits idle.
What a smaller N costs, stated plainly: less diversification per name (each
constituent is 20% at target rather than 10%), and caps that bind harder
(three same-protocol names are 60% of a five-name book). The §6.1 levels were
re-checked against N = 5 on the measured census — the curator cap binds first
(two same-curator names = 40% against 35%) and the waterfall's deterministic
redistribution handles it. The count rises — 6, 7, … 10 — as names age in,
measurement coverage widens, and scores move; each increase is a version bump
justified by census evidence, exactly like a cap change.
**When the count steps (v1.4.0).** Eligible-universe growth from a newly
measurable adapter class — such as the Aave v3 class this version adds —
never changes N by itself: **N is fixed until a methodology version changes
it**, and each increase is a version bump justified by census evidence,
exactly like a cap change. Membership within the fixed N can change at any
**reconstitution** — scheduled or extraordinary (§7.2) — because both invoke
the same selection run; between reconstitutions the composition is fixed and
weights drift with performance (§6.2). A newly measurable name therefore
enters exactly the way any other challenger does: through every gate, at a
reconstitution, with the incumbency buffer applied to scheduled runs (an
extraordinary reconstitution triggered by a §7.2 gate breach deliberately
bypasses it, as §7.2 records).
---
## 6. Weighting
**Equal weight**: each constituent's target is 1/N of the index, N per §5.1
(5 at glidepath start, target 10).
The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75%
safer than an 8.0, and score-weighting would make one estimate do two jobs, so a
small scoring error would move both membership and capital.
### 6.1 Look-through caps
Applied to the target weights by a deterministic cap-and-redistribution
waterfall, on four dimensions:
| Dimension | Cap |
| --------- | ---- |
| Protocol | 60% |
| Issuer | 100% |
| Curator | 35% |
| Chain | 70% |
Caps bind on the **look-through** dimension, not the vault name: two vaults on
one protocol consume that protocol's cap jointly. Where a cap binds, weight is
redistributed deterministically to uncapped names; the binding dimensions are
recorded on the selection run. If the cap system cannot be satisfied, the
reconstitution is infeasible and says so — caps are not quietly relaxed to force
a result.
**A null look-through key is membership in no group (v1.1.0).** A
protocol-native vault (Aave, Spark, Compound, Yearn) has no curator: it belongs
to no curator group and consumes no curator cap, in the trimming waterfall and
in every verification of it alike. This is not a relaxation of the fail-closed
rule — "there is no curator" is a measured fact about the vault's design, while
"the curator is unknown where one should exist" is missing metadata, and
missing metadata is an _eligibility_ exclusion decided before the waterfall
ever runs (a curated-platform vault with no curator attribution is excluded as
`curator_attribution_unavailable`). The same semantics apply to every cap
dimension.
**Cap levels are census-derived (v1.1.0).** The v1.0.0 levels
(35/50/35/70) were set before any census had run against production. The first
real census (2026-08-03, value date 2026-08-02) measured an eligible book that
no 10-name equal-weight composition can satisfy under them: the measurable
universe is Spark Savings and curated Morpho vaults in roughly equal number
(each ~50% of a ten-name book against a 35% protocol cap), and 90–100%
Circle-issued deposits (against a 50% issuer cap). A cap that admits no
composition at all protects nothing. The v1.1.0 levels are the tightest caps
the measured census satisfies with modest drift headroom: protocol 60%, issuer
100% (non-binding at glidepath start, stated plainly rather than pretended
at), curator and chain unchanged. These remain a **glidepath**: they
re-tighten as the eligible universe widens. Nothing re-tightens by itself — a
100% cap constrains nothing (weights always sum to exactly 100%, so the
waterfall excludes such a dimension outright rather than letting rounding
residue bind it) until a human lowers it, and like every cap change that takes
a new methodology version with its own hash. Re-tightening the issuer cap is
the first scheduled glidepath step once measurable non-Circle deposits exist,
and each quarterly census is the standing occasion to take it.
### 6.2 Weight drift
Between reconstitutions, weights **drift with performance**. They are not reset
to target daily. Resetting daily would silently rebalance the index every day
and publish a wrong level from day two onward — and both calculation engines
would agree on it, because they would share the same malformed input.
---
## 7. Reconstitution
### 7.1 Schedule
Scheduled reconstitutions are quarterly. A new composition is effective from a
stated value date and governs closes **after** that date (§8.3).
### 7.2 Extraordinary reconstitution
Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of
Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not
apply. An index deletion is not a claim that a tracker could have exited at that
price — see §16.
### 7.3 Evidence
Every reconstitution records the full census: every candidate considered, every
eligibility verdict with its reason, the ranking, the caps that bound, and the
resulting composition — hashed and signed.
### 7.4 The bench
The ranked eligible names that missed the cut are published with their rank.
"The next four names and exactly which rule keeps each one out" is part of the
product, not a byproduct.
---
## 8. Calculation
The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md`
(fixed-point representation, rounding, primitive operations, bounds). It governs
where it is more specific than this section.
### 8.1 Constituent return
For constituent _i_ over the interval ending at value date _t_:
```
r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1
```
`D` is distributions. The v1 universe is all-accruing, so **D = 0 by
construction** — yield accrues inside NAV per share. A vault that distributes is
ineligible (§4) precisely so this term cannot be silently wrong.
FX is a real measured price, not an assumed $1.00. A depeg therefore flows into
the index level mechanically, as a loss, rather than being invisible.
### 8.2 Index level
```
L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t)
```
Chain-linking is the definition, not an approximation. Opening weights are the
previous close's **drifted** weights (§6.2), never the composition targets —
except on the first close after a reconstitution took effect, which is what a
reconstitution means.
### 8.3 Reconstitution boundary
A composition effective for value date D applies from D's close **forward**. The
return _ending_ at D is computed under the **outgoing** composition; the new
targets open the next interval. Applying the incoming composition to D would
compute D's return over a constituent set that was not in force during it.
### 8.4 Gaps
If the previous accepted close is more than one day earlier, the interval is a
**multi-day return**, correctly labelled as such — never a silently mislabelled
one-day return. A multi-day interval may not span a reconstitution boundary: if
it would, the close defers rather than applying weights retroactively to days
they did not govern.
### 8.5 Back-calculated history (v1.3.0)
Pre-inception history MAY be reconstructed, under rules that keep it honest:
1. **The current book is held fixed.** A back-calculation clones the initial
composition verbatim (reason `back_calc`) and reprices it at pinned,
finalized historical blocks. It is NEVER a point-in-time re-selection:
eligibility as of past dates is not reconstructible from recorded data
(the Phase 0 finding), and pretending otherwise would be hindsight dressed
as history.
2. **Same engine, same evidence.** Every reconstructed close runs the full
production pipeline — sealed manifest, both engines, zero-tolerance
reconciliation, signed exported evidence.
3. **Labeled, always.** Reconstructed observations carry
`history_class = back_calculated` and that display status, regardless of
any other state. They are never presented as live, and the publication
target (lateness) does not apply to them.
4. **Scale-continuous, never restating.** The reconstructed segment is
anchored so that its final level times the TRUE boundary return (computed
target-weighted from the segment-end collection and the first live close's
sealed inputs) equals the live base, to within a stated rounding residual.
The live chain — including the first live close's inception zero return —
is never modified; acceptance is terminal.
5. **PPR basis disclosure.** A PPR fixing whose window includes reconstructed
observations states so (`basis` on the fixing): the rate is real arithmetic
over a partially reconstructed series, and the reader decides what that is
worth. Endpoints are still never substituted.
### 8.6 Precision
Internal arithmetic is scaled integer at 8 decimal places with half-even
rounding at defined points only. Published levels are stated at 2 decimal
places. Value date, calculation timestamp and publication timestamp are distinct
fields and are never conflated.
---
## 9. Data, provenance and verification
### 9.1 NAV
NAV is read on-chain at a **pinned block** per chain, after that chain's
finality rule is satisfied, by the vault's registered **adapter class**
(v1.4.0). Two classes exist; each defines "one share" so that the return
ratio `NAV_t / NAV_{t-1}` measures the growth in **asset value per held
unit**: for an ERC-4626 vault the holder's share count is constant and each
share's asset-equivalent value grows by the ratio; for an aToken the
holder's `balanceOf` itself grows by the ratio **absent holder flows**
(deposits, withdrawals and transfers move scaled principal and are not
return). The normative arithmetic is
`packages/shared/src/indices/ARITHMETIC.md` §NAV.
**ERC-4626** — `convertToAssets(1 share)`. Before the read is accepted:
`asset()` must still bind to the expected deposit asset; `totalSupply()` must be
non-zero; the resulting NAV must be plausible; and a move beyond **500 bps**
from the previous accepted NAV is **rejected**, not clamped — a clamped absurd
input produces a plausible wrong number, the failure a benchmark can least
afford.
**Aave v3 aTokens** — a rebasing receipt: holder balance = scaled balance ×
the pool's liquidity index, so NAV is defined **per scaled unit** and read as
the pool's `getReserveNormalizedIncome(underlying)`, a ray (27-decimal) value
that the pool computes with linear accrual to the queried block — which is
what makes a pinned-block read correct without replicating rate math off-chain.
The ray is normalized to the internal 8-decimal scale with half-even rounding.
Before the read is accepted, the **identity chain is re-asserted on every
read**: `UNDERLYING_ASSET_ADDRESS()` must bind to the expected deposit asset;
`totalSupply()` must be non-zero; `POOL()` must equal the pool the census probe
verified and froze at registration — an adapter registered **without** that
pool anchor is refused outright, never priced on the self-reported pool — and
the pool's reserve data for the underlying must name this aToken back. A pool
swap or proxy re-point after registration therefore fails closed instead of
feeding a plausible fake income stream. Additionally, a reserve carrying
**material recognized bad debt** fails the reading closed — nominal balance
growth on such a reserve is not realizable. Materiality (v1.4.1) is bounded
relative to the reserve: a recognized deficit **strictly greater than 0.1
basis point (1/1,000,000) of total aToken supply** — both figures
underlying-denominated, so the ratio is unit-free — fails closed; a deficit
at or below the bound is **de minimis** (dust-scale residue of resolved
liquidations, orders of magnitude beneath the index's own 8-decimal
representation and daily-return scale), and the reading proceeds on the
nominal basis with the exact deficit recorded as a warning in the
collection evidence. The v1.4.0 rule was absolute (any deficit > 0); the
first live close under it demonstrated that a long-lived reserve routinely
carries sub-dollar recognized dust, which would defer the close
indefinitely without representing any measurable impairment. **Any**
failure to read the deficit getter still fails closed at NAV time.
Deficit-getter support is for that reason a **registration requirement**: the
census probe refuses pools whose getter does not respond, and pre-3.3
deployments without it are out of scope. The plausibility bound and the
500 bps anomaly rejection are shared with the ERC-4626 class verbatim.
Share and asset decimals are **probed on-chain at registration** and persisted.
They are never defaulted: a vault without probed conformance is not priced, the
collection is therefore incomplete, and the close defers. (For the Aave class
the "share" unit is definitionally the ray scale, recorded at registration
rather than probed; the underlying's decimals are probed like any other.)
### 9.2 FX
Push oracles only, from the families `chainlink`, `chronicle`, `redstone`,
`api3`. The registry is keyed by **token address + chain**, never by symbol —
symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark.
The published FX is the **median of the responsive quorum**. A quote more than
200 bps from that median is **flagged and still counted** — it is not discarded.
That is deliberate, and worth stating plainly because the intuitive rule is the
opposite. Discarding a quote requires deciding it is wrong, and the median is
already robust to a single bad source without that decision. More importantly,
exclusion would make aggregation depend on a _prior pass's_ labels: replaying the
stored evidence for a past close could then produce a different number from the
one published, which would make the evidence package unverifiable. Flagging
records the disagreement in the evidence without letting it change the
arithmetic.
Independence is counted by **oracle family**, and a single feed address may not
be registered under more than one family — quorum is a claim about independent
sources, not about rows.
**A known dependency, stated because it is invisible otherwise.** Chronicle's
mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller
except a short allowlist, which includes the zero address. PHIL10 reads them as
an off-chain indexer via `eth_call` with no `from`, which defaults to the zero
address, so the reads succeed — but that permission is Chronicle's to revoke. If
it were revoked, those quotes would begin erroring rather than returning a wrong
number, the affected assets would fall from three responsive sources to two, and
pricing would continue in a recorded degraded state. The failure mode is
therefore visible and safe, but the dependency is real and is not something
PHIL10 controls.
Losing quorum does not produce a price: it produces a recorded degraded state
with a reason. An asset with fewer than three independent feeds is a founder
decision, not something the collector works around: such an asset is excluded
from the universe by the FX-quorum gate (§4) rather than silently priced.
### 9.3 Collection coherence
Every input row is stamped with a collection id. A completeness sentinel is
written **last**, and only when every constituent produced both a NAV and a
median. A crashed or partial collection leaves no sentinel and is never
consumed — the close reads the last complete collection, or defers.
### 9.4 Dual-engine reconciliation
Every close is computed twice: a primary scaled-integer engine in TypeScript and
an independent engine in PostgreSQL `numeric`, over the **same sealed inputs**
but on a different arithmetic substrate. Agreement is required at **zero
tolerance** on the level, the daily return, each constituent return and each
close weight. Disagreement **blocks publication**; it does not average, pick a
side, or warn.
### 9.5 Evidence
Every close emits a signed evidence package: the sealed inputs, both engines'
results, the reconciliation, the governing composition and methodology version,
engine versions and hashes. Signatures are Ed25519; the public half of every
signing key is registered in an append-only registry before use, so historical
signatures remain verifiable across key rotation.
### 9.6 Append-only
Observations, inputs, runs and evidence are **insert-only**, enforced by
database triggers, including protection against TRUNCATE. A correction is a new
revision plus a notice (§13). History is never edited.
---
## 10. Staleness ladder and statuses
| Input age at close | Effect |
| ------------------ | --------------------------------------------------------- |
| ≤ 6h | Normal |
| > 6h | Constituent flagged; close proceeds |
| > 48h | Close proceeds, status records calculation on stale input |
| > 72h | **Close is `not_calculated`** |
A single constituent past 72h makes the whole close `not_calculated`.
Constituents are **never dropped and renormalized to rescue a close** — that
would silently change the composition on precisely the days the data is worst.
A carried-forward annualized rate is never accrued.
**Status vocabulary** (fixed; these exact words appear in the API):
`preliminary`, `official`, `revised`, `delayed`, `insufficient_data`,
`not_calculated`, `back_calculated`.
An honest gap is **permanent**: once a later close has been accepted, a skipped
date is not retroactively filled, because doing so would break the internal
chaining of an already-signed series.
---
## 11. Publication
Closes are calculated after the value date's close instant and after chain
finality. The target publication time is 16:30 UTC. A late close is published
late and labelled, never backdated. A close that cannot be computed is recorded
with the reason — silence is not a permitted outcome, and a dead-man's watchdog
alerts if a value date passes with no observation.
---
## 12. Depeg ladder
Evaluated on the deposit asset against a two-source-minimum quorum:
| Condition | Action |
| --------------------------- | -------------------------------------------- |
| < $0.985 for 4 hours | Review flagged |
| < $0.97 for 15 minutes | Extraordinary review flagged |
| < $0.95, quorum-confirmed | **Presumptive removal** |
| < $0.95, single source only | Extraordinary flagged (removal needs quorum) |
Flags annotate a close; they never block it. Severity is **monotonic within an
open episode** — it can only rise. It clears only through the quorum-guarded
recovery exit that closes the episode; a single low-confidence tick can never
downgrade a confirmed removal and re-admit a still-depegged vault.
A depeg is also visible in the level itself, because FX is measured (§8.1).
---
## 13. Corrections and restatement
An error is corrected by **new revisions plus a numbered public notice** stating
what changed, why, which value dates are affected and what the levels were
before and after. Prior revisions remain queryable forever. The methodology
version and composition that governed each revision remain attached to it.
---
## 14. Governance
- **Index committee:** two founders. The external seat is deliberately **open**
(see §0) and will be filled when the right person is found rather than for
appearance.
- **Methodology changes** are new versions with new hashes. Non-emergency
changes carry a public consultation period once the index is public.
- **Conflicts:** Philidor operates no product tracking PHIL10, and none is
planned for v1. Risk-assessment commercial relationships with constituents'
operators, where they exist, are disclosed as a category. The controlling
rule, which admits no exception: **money can buy coverage, custom products and
calculation services; it can never buy a risk score or a seat in a standard
index.**
- **Cessation:** if PHIL10 stops being calculated, that is announced with a
notice and the historical series remains published and verifiable.
---
## 15. Regulatory status
PHIL10 is private and unpublished, licensed to no one, and tracked by no
product. No regulatory-status claim is made in this version. A
counsel-reviewed benchmark statement is a prerequisite for public inception, not
for this document.
Nothing here is investment advice.
---
## 16. Known limitations
Stated exactly, because a rulebook that hides them is not worth publishing:
1. **The universe is small and concentrated.** Five names at glidepath start
(§5.1), drawn from a single-digit eligible set dominated by two protocols.
Caps (§6.1) and the constituent count are both set at glidepath levels for
exactly this reason, and the binding dimensions are published per
reconstitution.
2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is
measured; the horizon is not observable on-chain.
3. **Index deletion is not tracker realizability.** An extraordinary
reconstitution removes a name from the index; it does not assert that a
holder could have exited at that price, or at all.
4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps
NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic
loss looks implausible, so the close defers rather than recording it. This is
deliberate fail-closed behaviour and an open founder decision: a crisis
confirmation path is required before PHIL10 can claim to measure a crisis.
5. **No external methodology review** (§0).
6. **No public track record.** The series is preliminary and the soak is
private. Elapsed operating time cannot be simulated or shortened.
7. **Back-calculated history is a fixed-book reconstruction, not point-in-time
history** (§8.5, v1.3.0). Point-in-time eligibility is not reconstructable,
so the reconstruction holds the current book fixed and says so on every
observation. Selection history before inception does not exist and is not
claimed.
---
## 17. Version history
| Version | Date | Change |
| ------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. |
| 1.1.0 | 2026-08-03 | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key = no group, with curated-platform attribution failures excluded at eligibility; mechanism-attestation evidence path for the all-accruing gate (Spark). |
| 1.2.0 | 2026-08-03 | Constituent count N = 5 at glidepath start (census: 5 names clear every gate; target remains 10, each step back is a version — §5.1). |
| 1.3.0 | 2026-08-03 | Back-calculated history rules (§8.5): fixed-book reconstruction at pinned blocks, full pipeline + evidence, always labeled, scale-continuous anchoring, PPR basis disclosure. |
| 1.4.0 | 2026-08-04 | Aave v3 aToken adapter class: scaled-unit NAV from pool normalized income, identity anchoring, deficit fail-closed (§9.1); Aave withdrawability probe (§4.2); Aave accrual attestation (§4.1); count steps only at a reconstitution (§5.1). |
| 1.4.1 | 2026-08-04 | Deficit materiality bound (§9.1): recognized reserve deficit fails closed only above 0.1 bp of total aToken supply; at or below the bound the reading proceeds on the nominal basis with the deficit recorded as a warning. Prompted by the first live Aave close: mainnet aEthUSDT carries a sub-dollar recognized dust deficit that wedged the close under the absolute v1.4.0 rule. |
| Deficit materiality bound (§9.1): a recognized reserve deficit fails closed only above 0.1 bp of total aToken supply; at or below it the reading proceeds on the nominal basis with the deficit recorded as a warning. |
| 1.4.0 | 2026-08-04 | PHIL10 — Index Methodology sha256 3d40cb4e7a91da0b29e03949836a4876957b3e693ad47d750f7736261bc6bd88 Read the document (39 KB)# PHIL10 — Index Methodology
**Index:** The Philidor Onchain Dollar Yield Index 10
**Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD
**Methodology version:** 1.4.0
**Administrator:** Philidor Labs
---
## 0. Status of this document and of the index
**PHIL10 is not an official benchmark and has no official inception date.** This
document governs a **private operational soak**: the engine calculates a daily
level from real on-chain data, on a real schedule, under real fail-closed rules,
and every live observation it produces carries the status `preliminary`
(reconstructed history carries `back_calculated` — §8.5). Nothing is
published publicly, no product may track it, and the level series is not a track
record.
Two things follow, and they are stated here because a rulebook that overclaims
is worse than none:
1. **Official inception is a separate, later act.** It requires a base date, a
base value of 100.00, a public preliminary period, and the governance
apparatus in §14 actually operating. Until then the series is a systems
artefact, not a benchmark.
2. **No external methodology review has been performed.** The founders decided
on 2026-07-22 to hold the external reviewer seat open until the right person
is found rather than fill it for form's sake. Until that review exists, the
compensating controls are: this document published in full, the dual-engine
reconciliation of §9.4, the signed evidence of §9.5, and the honest
limitations of §16.
This document is versioned and content-hashed. The hash of the exact bytes of
this file is recorded in `index_methodology_versions.content_hash`, and every
composition and observation references the methodology version under which it
was produced.
---
## 1. Objective
PHIL10 is a rules-based, total-return index designed to measure a diversified
set of risk-qualified, implementation-eligible USD-denominated onchain yield
strategies.
It answers one question: _what does a disciplined dollar allocator actually earn
across the onchain venues that pass a real risk screen and can genuinely be
entered and exited?_
It is deliberately **not** a market-coverage index. Breadth is not the goal;
qualification is. Names beyond the constituent count (§5.1) are excluded on
purpose, and the published bench (§7.4) states exactly which rule excluded each
one.
---
## 2. Definitions
| Term | Meaning in this document |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. |
| **Close** | The daily calculation producing one official level for one value date. |
| **Constituent** | A vault included in the composition governing a value date. |
| **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. |
| **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). |
| **NAV per share** | The adapter-class per-unit value read on-chain at the pinned close block (§9.1): `convertToAssets(1 share)` for ERC-4626 vaults; the pool's normalized income per scaled aToken unit for Aave v3 (v1.4.0). |
| **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. |
| **Observation** | One published (index, value date, revision) row with a level and a status. |
| **Collection** | One complete run of the input collector, identified by a collection id. |
---
## 3. Universe
A tracked vault is in the candidate universe if **all** of the following hold.
Every exclusion carries a machine-readable reason, so the census can state why a
name is out without a human re-deriving it.
1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`.
2. **Single-asset exposure.** A vault whose asset components list more than one
asset (e.g. USDC/WETH) is excluded — it is not a dollar vault.
3. **Active and not shut down.**
4. **Chain is not held out.** Held-out chain ids are enumerated in code and
currently comprise chain `9745`.
5. **The asset address is known.** Identity is (address, chain) everywhere
downstream — FX feeds, adapters, caps. A candidate without an asset address
cannot be carried honestly, so it is excluded rather than symbol-matched.
**Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not
merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS,
FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others
enumerated in code. The list exists so the exclusion is reviewable, and so a new
synthetic that slips past canonicalization is still caught by name.
**Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to
`circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and
is treated as a distinct asset that nonetheless consumes the Tether issuer cap.
---
## 4. Eligibility
A universe member must additionally pass **every** gate below. Order affects
only which reason is reported first.
| Gate | Threshold |
| ------------------------- | ---------------------------------------------------------------------------- |
| Risk vectors readable | Required — see fail-closed rule |
| Hard-fail flag | Must be absent |
| Depeg presumptive removal | Must be absent |
| Incident clamp | Must be absent |
| All-accruing | Required (v1 universe pays no distributions) |
| Reviewed | Required |
| Philidor risk score | ≥ **8.0** (Prime) |
| Vault TVL | ≥ **$5,000,000** |
| Vault age | ≥ **90 days** |
| Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** |
| Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** |
| Stressed clip | ≤ **20%** of vault TVL |
| FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain |
The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a
vault whose deposit asset cannot reach a price quorum on its chain is not priced
conservatively, it cannot be priced **at all**, and including it would stop the
index rather than degrade it. Independence is counted by oracle _family_, not by
contract: two feeds from the same provider are one source.
### 4.1 The fail-closed rule
**"We could not measure it" and "it passed" must never produce the same
outcome.** A candidate whose liquidity test could not be executed, or whose risk
vectors could not be read, is **ineligible** — it is never waved through. These
are reported as distinct reasons (`liquidity_test_unavailable`,
`risk_vectors_unavailable`) so the census can tell an unmeasurable name apart
from an illiquid one.
**All-accruing evidence (v1.1.0).** The all-accruing gate (§4) is evidenced by
the ingestion pipeline's reward observations. Because an empty reward set is
only informative when the pipeline demonstrably observes rewards for that
protocol, a protocol with no recorded reward stream is normally _unverifiable_
— excluded, not passed. One documented exception exists: a **mechanism
attestation**, a reviewed and provenance-carrying claim that the protocol's
vault design structurally cannot distribute value outside NAV (recorded in
code as `ACCRUAL_MECHANISM_ATTESTATIONS`). Currently attested (v1.4.0):
- **Spark/Sky Savings tokens**, whose yield accrues exclusively through the
Savings Rate raising `convertToAssets`; reviewed 2026-08-03.
- **Aave v3 aTokens**, which accrue depositor value exclusively through the
pool liquidity index raising `balanceOf` (read as the pool's
`getReserveNormalizedIncome` — §9.1); the aToken contract itself exposes no
distribution or claim mechanism. External Aave incentives
(incentives-controller and Merit campaigns) are distributed by separate
contracts, and the platform's Aave protocol adapter records them as reward
streams when they exist — a recorded stream still fails the gate as
`external_rewards` regardless of this attestation, which covers only the
missing pipeline-observability signal. Reviewed 2026-08-04.
An attestation substitutes only for
the missing pipeline-observability signal. It never outranks a recorded
reward stream, never bypasses evidence freshness, and never bypasses the
`apr_net = base_apr + Σ rewards` decomposition cross-check — an attested
protocol that starts paying incentives is caught by either surviving
detector.
### 4.2 What the liquidity test measures, and what it assumes
Stated plainly because the boundary is real:
- **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both
clip sizes, read on-chain at a pinned block.
- **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which
folds in the vault's currently available liquidity.
- **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an
underlying position unwinds, so tier-2 capacity is evaluated against total
assets, which **assumes an orderly 7-day unwind**. The assumption is recorded
in the signed evidence for every candidate so a reader sees it rather than
infers it.
This is a known limitation, restated in §16, and a live founder decision: either
accept the orderly-unwind assumption or require real unwind evidence and exclude
names that cannot supply it.
**Aave v3 withdrawability (v1.4.0).** An Aave v3 reserve has no
`previewWithdraw`/`maxWithdraw` surface, so its probe measures the mechanism it
actually has, still at a pinned block and still with no default-true path:
- **Capacity** is `min(probe holder's aToken balance, the reserve's available
liquidity)` — the underlying actually sitting in the aToken contract — and
both liquidity tiers gate on that figure. Available liquidity is
instantaneous; a 7-day orderly window can only replenish it (borrower
repayments, new supply), so gating tier 2 on the instantaneous figure is
conservative, and that assumption is recorded in the evidence.
- **Executability, not just balances.** Balances alone can record passes for
withdrawals that would revert, so the probe additionally requires the
reserve's configuration to show **active and unpaused** (a frozen reserve
blocks new supply but not withdrawal, so frozen alone does not fail it),
and requires a **debt-free probe holder**: a collateralized borrower's
withdrawal is bounded by health-factor math the probe does not model, so a
holder carrying any debt is an unmeasurable proxy, not a passing one.
- **Exit cost is zero by mechanism**, conditional on the above: withdrawal is
1:1 in the underlying when available liquidity suffices — there is no
share/asset conversion and no pool-level fee — and the evidence records it
as such rather than measuring it through a preview that does not exist on
this ABI.
- The **stressed clip** is evaluated against the reserve's total aToken
supply, mirroring the ERC-4626 total-assets basis.
As on the ERC-4626 path, a candidate with no configured probe holder is
unmeasurable and therefore ineligible.
---
## 5. Selection
1. Rank all eligible candidates by the **total, data-driven ordering**: risk
score descending, then vault age descending, then TVL descending, then
ref_id ascending. Every tie-break is deterministic — a selection that could
depend on map iteration order could not be reproduced, which would make the
evidence chain worthless.
2. Take the top **N** (§5.1).
3. **Incumbency buffer.** An incumbent constituent is displaced only if the
challenger beats it by **more than 0.2** of a risk score point **and** by
**more than 3** rank places — both, strictly; clearing one alone retains
the incumbent, and a challenger at exactly 0.2 points or exactly 3 ranks
has not cleared it. (Corrected in v1.2.0: earlier versions of this document
said "or", describing a rule the engine has never implemented — turnover
must be clearly earned on both measures.) This suppresses churn from noise.
The buffer is bypassed by extraordinary events (§12) — a hard-failed name
leaves immediately.
If fewer than N eligible names exist, the reconstitution is **infeasible** and
reports why. PHIL10 does not publish an N-name index with N−1 names, and does
not lower a gate to reach the number.
### 5.1 Constituent count (v1.2.0)
**N = 5 at glidepath start. The target remains 10** — it is the index's name
and its destination — and each step back toward it is a methodology version.
This is the census speaking, not a preference. The first production census
(2026-08-03) measured **5** names clearing every gate. The gap to 10 is not a
tuning problem: at that census the calculation engine priced ERC-4626 vaults
only, which excluded rebasing money-market receipts (Aave aTokens, Compound
Comet) regardless of their quality; reward-observability and
executed-liquidity evidence exclude what cannot yet be measured; and the next
nearest name enters by vault age in September 2026. As of v1.4.0 the engine
additionally prices **Aave v3 aTokens** through a dedicated adapter class
(§9.1) with a matching liquidity probe (§4.2) and accrual attestation (§4.1);
Compound Comet remains unsupported (its supply index only advances on accrual,
and honest pinned-block support would require present-value rate math the
engine does not approximate). The alternatives to reducing N were all worse:
relaxing a gate (forbidden — §4.1), widening the universe into synthetic
dollars (§3 excludes them by name, deliberately), or publishing nothing for
months while a five-name book of measured, risk-qualified names sits idle.
What a smaller N costs, stated plainly: less diversification per name (each
constituent is 20% at target rather than 10%), and caps that bind harder
(three same-protocol names are 60% of a five-name book). The §6.1 levels were
re-checked against N = 5 on the measured census — the curator cap binds first
(two same-curator names = 40% against 35%) and the waterfall's deterministic
redistribution handles it. The count rises — 6, 7, … 10 — as names age in,
measurement coverage widens, and scores move; each increase is a version bump
justified by census evidence, exactly like a cap change.
**When the count steps (v1.4.0).** Eligible-universe growth from a newly
measurable adapter class — such as the Aave v3 class this version adds —
never changes N by itself: **N is fixed until a methodology version changes
it**, and each increase is a version bump justified by census evidence,
exactly like a cap change. Membership within the fixed N can change at any
**reconstitution** — scheduled or extraordinary (§7.2) — because both invoke
the same selection run; between reconstitutions the composition is fixed and
weights drift with performance (§6.2). A newly measurable name therefore
enters exactly the way any other challenger does: through every gate, at a
reconstitution, with the incumbency buffer applied to scheduled runs (an
extraordinary reconstitution triggered by a §7.2 gate breach deliberately
bypasses it, as §7.2 records).
---
## 6. Weighting
**Equal weight**: each constituent's target is 1/N of the index, N per §5.1
(5 at glidepath start, target 10).
The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75%
safer than an 8.0, and score-weighting would make one estimate do two jobs, so a
small scoring error would move both membership and capital.
### 6.1 Look-through caps
Applied to the target weights by a deterministic cap-and-redistribution
waterfall, on four dimensions:
| Dimension | Cap |
| --------- | ---- |
| Protocol | 60% |
| Issuer | 100% |
| Curator | 35% |
| Chain | 70% |
Caps bind on the **look-through** dimension, not the vault name: two vaults on
one protocol consume that protocol's cap jointly. Where a cap binds, weight is
redistributed deterministically to uncapped names; the binding dimensions are
recorded on the selection run. If the cap system cannot be satisfied, the
reconstitution is infeasible and says so — caps are not quietly relaxed to force
a result.
**A null look-through key is membership in no group (v1.1.0).** A
protocol-native vault (Aave, Spark, Compound, Yearn) has no curator: it belongs
to no curator group and consumes no curator cap, in the trimming waterfall and
in every verification of it alike. This is not a relaxation of the fail-closed
rule — "there is no curator" is a measured fact about the vault's design, while
"the curator is unknown where one should exist" is missing metadata, and
missing metadata is an _eligibility_ exclusion decided before the waterfall
ever runs (a curated-platform vault with no curator attribution is excluded as
`curator_attribution_unavailable`). The same semantics apply to every cap
dimension.
**Cap levels are census-derived (v1.1.0).** The v1.0.0 levels
(35/50/35/70) were set before any census had run against production. The first
real census (2026-08-03, value date 2026-08-02) measured an eligible book that
no 10-name equal-weight composition can satisfy under them: the measurable
universe is Spark Savings and curated Morpho vaults in roughly equal number
(each ~50% of a ten-name book against a 35% protocol cap), and 90–100%
Circle-issued deposits (against a 50% issuer cap). A cap that admits no
composition at all protects nothing. The v1.1.0 levels are the tightest caps
the measured census satisfies with modest drift headroom: protocol 60%, issuer
100% (non-binding at glidepath start, stated plainly rather than pretended
at), curator and chain unchanged. These remain a **glidepath**: they
re-tighten as the eligible universe widens. Nothing re-tightens by itself — a
100% cap constrains nothing (weights always sum to exactly 100%, so the
waterfall excludes such a dimension outright rather than letting rounding
residue bind it) until a human lowers it, and like every cap change that takes
a new methodology version with its own hash. Re-tightening the issuer cap is
the first scheduled glidepath step once measurable non-Circle deposits exist,
and each quarterly census is the standing occasion to take it.
### 6.2 Weight drift
Between reconstitutions, weights **drift with performance**. They are not reset
to target daily. Resetting daily would silently rebalance the index every day
and publish a wrong level from day two onward — and both calculation engines
would agree on it, because they would share the same malformed input.
---
## 7. Reconstitution
### 7.1 Schedule
Scheduled reconstitutions are quarterly. A new composition is effective from a
stated value date and governs closes **after** that date (§8.3).
### 7.2 Extraordinary reconstitution
Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of
Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not
apply. An index deletion is not a claim that a tracker could have exited at that
price — see §16.
### 7.3 Evidence
Every reconstitution records the full census: every candidate considered, every
eligibility verdict with its reason, the ranking, the caps that bound, and the
resulting composition — hashed and signed.
### 7.4 The bench
The ranked eligible names that missed the cut are published with their rank.
"The next four names and exactly which rule keeps each one out" is part of the
product, not a byproduct.
---
## 8. Calculation
The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md`
(fixed-point representation, rounding, primitive operations, bounds). It governs
where it is more specific than this section.
### 8.1 Constituent return
For constituent _i_ over the interval ending at value date _t_:
```
r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1
```
`D` is distributions. The v1 universe is all-accruing, so **D = 0 by
construction** — yield accrues inside NAV per share. A vault that distributes is
ineligible (§4) precisely so this term cannot be silently wrong.
FX is a real measured price, not an assumed $1.00. A depeg therefore flows into
the index level mechanically, as a loss, rather than being invisible.
### 8.2 Index level
```
L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t)
```
Chain-linking is the definition, not an approximation. Opening weights are the
previous close's **drifted** weights (§6.2), never the composition targets —
except on the first close after a reconstitution took effect, which is what a
reconstitution means.
### 8.3 Reconstitution boundary
A composition effective for value date D applies from D's close **forward**. The
return _ending_ at D is computed under the **outgoing** composition; the new
targets open the next interval. Applying the incoming composition to D would
compute D's return over a constituent set that was not in force during it.
### 8.4 Gaps
If the previous accepted close is more than one day earlier, the interval is a
**multi-day return**, correctly labelled as such — never a silently mislabelled
one-day return. A multi-day interval may not span a reconstitution boundary: if
it would, the close defers rather than applying weights retroactively to days
they did not govern.
### 8.5 Back-calculated history (v1.3.0)
Pre-inception history MAY be reconstructed, under rules that keep it honest:
1. **The current book is held fixed.** A back-calculation clones the initial
composition verbatim (reason `back_calc`) and reprices it at pinned,
finalized historical blocks. It is NEVER a point-in-time re-selection:
eligibility as of past dates is not reconstructible from recorded data
(the Phase 0 finding), and pretending otherwise would be hindsight dressed
as history.
2. **Same engine, same evidence.** Every reconstructed close runs the full
production pipeline — sealed manifest, both engines, zero-tolerance
reconciliation, signed exported evidence.
3. **Labeled, always.** Reconstructed observations carry
`history_class = back_calculated` and that display status, regardless of
any other state. They are never presented as live, and the publication
target (lateness) does not apply to them.
4. **Scale-continuous, never restating.** The reconstructed segment is
anchored so that its final level times the TRUE boundary return (computed
target-weighted from the segment-end collection and the first live close's
sealed inputs) equals the live base, to within a stated rounding residual.
The live chain — including the first live close's inception zero return —
is never modified; acceptance is terminal.
5. **PPR basis disclosure.** A PPR fixing whose window includes reconstructed
observations states so (`basis` on the fixing): the rate is real arithmetic
over a partially reconstructed series, and the reader decides what that is
worth. Endpoints are still never substituted.
### 8.6 Precision
Internal arithmetic is scaled integer at 8 decimal places with half-even
rounding at defined points only. Published levels are stated at 2 decimal
places. Value date, calculation timestamp and publication timestamp are distinct
fields and are never conflated.
---
## 9. Data, provenance and verification
### 9.1 NAV
NAV is read on-chain at a **pinned block** per chain, after that chain's
finality rule is satisfied, by the vault's registered **adapter class**
(v1.4.0). Two classes exist; each defines "one share" so that the return
ratio `NAV_t / NAV_{t-1}` measures the growth in **asset value per held
unit**: for an ERC-4626 vault the holder's share count is constant and each
share's asset-equivalent value grows by the ratio; for an aToken the
holder's `balanceOf` itself grows by the ratio **absent holder flows**
(deposits, withdrawals and transfers move scaled principal and are not
return). The normative arithmetic is
`packages/shared/src/indices/ARITHMETIC.md` §NAV.
**ERC-4626** — `convertToAssets(1 share)`. Before the read is accepted:
`asset()` must still bind to the expected deposit asset; `totalSupply()` must be
non-zero; the resulting NAV must be plausible; and a move beyond **500 bps**
from the previous accepted NAV is **rejected**, not clamped — a clamped absurd
input produces a plausible wrong number, the failure a benchmark can least
afford.
**Aave v3 aTokens** — a rebasing receipt: holder balance = scaled balance ×
the pool's liquidity index, so NAV is defined **per scaled unit** and read as
the pool's `getReserveNormalizedIncome(underlying)`, a ray (27-decimal) value
that the pool computes with linear accrual to the queried block — which is
what makes a pinned-block read correct without replicating rate math off-chain.
The ray is normalized to the internal 8-decimal scale with half-even rounding.
Before the read is accepted, the **identity chain is re-asserted on every
read**: `UNDERLYING_ASSET_ADDRESS()` must bind to the expected deposit asset;
`totalSupply()` must be non-zero; `POOL()` must equal the pool the census probe
verified and froze at registration — an adapter registered **without** that
pool anchor is refused outright, never priced on the self-reported pool — and
the pool's reserve data for the underlying must name this aToken back. A pool
swap or proxy re-point after registration therefore fails closed instead of
feeding a plausible fake income stream. Additionally, a reserve carrying
**recognized bad debt** (an Aave 3.3+ deficit greater than zero) fails the
reading closed — nominal balance growth on such a reserve is not realizable —
and **any** failure to read the deficit getter fails closed at NAV time.
Deficit-getter support is for that reason a **registration requirement**: the
census probe refuses pools whose getter does not respond, and pre-3.3
deployments without it are out of scope. The plausibility bound and the
500 bps anomaly rejection are shared with the ERC-4626 class verbatim.
Share and asset decimals are **probed on-chain at registration** and persisted.
They are never defaulted: a vault without probed conformance is not priced, the
collection is therefore incomplete, and the close defers. (For the Aave class
the "share" unit is definitionally the ray scale, recorded at registration
rather than probed; the underlying's decimals are probed like any other.)
### 9.2 FX
Push oracles only, from the families `chainlink`, `chronicle`, `redstone`,
`api3`. The registry is keyed by **token address + chain**, never by symbol —
symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark.
The published FX is the **median of the responsive quorum**. A quote more than
200 bps from that median is **flagged and still counted** — it is not discarded.
That is deliberate, and worth stating plainly because the intuitive rule is the
opposite. Discarding a quote requires deciding it is wrong, and the median is
already robust to a single bad source without that decision. More importantly,
exclusion would make aggregation depend on a _prior pass's_ labels: replaying the
stored evidence for a past close could then produce a different number from the
one published, which would make the evidence package unverifiable. Flagging
records the disagreement in the evidence without letting it change the
arithmetic.
Independence is counted by **oracle family**, and a single feed address may not
be registered under more than one family — quorum is a claim about independent
sources, not about rows.
**A known dependency, stated because it is invisible otherwise.** Chronicle's
mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller
except a short allowlist, which includes the zero address. PHIL10 reads them as
an off-chain indexer via `eth_call` with no `from`, which defaults to the zero
address, so the reads succeed — but that permission is Chronicle's to revoke. If
it were revoked, those quotes would begin erroring rather than returning a wrong
number, the affected assets would fall from three responsive sources to two, and
pricing would continue in a recorded degraded state. The failure mode is
therefore visible and safe, but the dependency is real and is not something
PHIL10 controls.
Losing quorum does not produce a price: it produces a recorded degraded state
with a reason. An asset with fewer than three independent feeds is a founder
decision, not something the collector works around: such an asset is excluded
from the universe by the FX-quorum gate (§4) rather than silently priced.
### 9.3 Collection coherence
Every input row is stamped with a collection id. A completeness sentinel is
written **last**, and only when every constituent produced both a NAV and a
median. A crashed or partial collection leaves no sentinel and is never
consumed — the close reads the last complete collection, or defers.
### 9.4 Dual-engine reconciliation
Every close is computed twice: a primary scaled-integer engine in TypeScript and
an independent engine in PostgreSQL `numeric`, over the **same sealed inputs**
but on a different arithmetic substrate. Agreement is required at **zero
tolerance** on the level, the daily return, each constituent return and each
close weight. Disagreement **blocks publication**; it does not average, pick a
side, or warn.
### 9.5 Evidence
Every close emits a signed evidence package: the sealed inputs, both engines'
results, the reconciliation, the governing composition and methodology version,
engine versions and hashes. Signatures are Ed25519; the public half of every
signing key is registered in an append-only registry before use, so historical
signatures remain verifiable across key rotation.
### 9.6 Append-only
Observations, inputs, runs and evidence are **insert-only**, enforced by
database triggers, including protection against TRUNCATE. A correction is a new
revision plus a notice (§13). History is never edited.
---
## 10. Staleness ladder and statuses
| Input age at close | Effect |
| ------------------ | --------------------------------------------------------- |
| ≤ 6h | Normal |
| > 6h | Constituent flagged; close proceeds |
| > 48h | Close proceeds, status records calculation on stale input |
| > 72h | **Close is `not_calculated`** |
A single constituent past 72h makes the whole close `not_calculated`.
Constituents are **never dropped and renormalized to rescue a close** — that
would silently change the composition on precisely the days the data is worst.
A carried-forward annualized rate is never accrued.
**Status vocabulary** (fixed; these exact words appear in the API):
`preliminary`, `official`, `revised`, `delayed`, `insufficient_data`,
`not_calculated`, `back_calculated`.
An honest gap is **permanent**: once a later close has been accepted, a skipped
date is not retroactively filled, because doing so would break the internal
chaining of an already-signed series.
---
## 11. Publication
Closes are calculated after the value date's close instant and after chain
finality. The target publication time is 16:30 UTC. A late close is published
late and labelled, never backdated. A close that cannot be computed is recorded
with the reason — silence is not a permitted outcome, and a dead-man's watchdog
alerts if a value date passes with no observation.
---
## 12. Depeg ladder
Evaluated on the deposit asset against a two-source-minimum quorum:
| Condition | Action |
| --------------------------- | -------------------------------------------- |
| < $0.985 for 4 hours | Review flagged |
| < $0.97 for 15 minutes | Extraordinary review flagged |
| < $0.95, quorum-confirmed | **Presumptive removal** |
| < $0.95, single source only | Extraordinary flagged (removal needs quorum) |
Flags annotate a close; they never block it. Severity is **monotonic within an
open episode** — it can only rise. It clears only through the quorum-guarded
recovery exit that closes the episode; a single low-confidence tick can never
downgrade a confirmed removal and re-admit a still-depegged vault.
A depeg is also visible in the level itself, because FX is measured (§8.1).
---
## 13. Corrections and restatement
An error is corrected by **new revisions plus a numbered public notice** stating
what changed, why, which value dates are affected and what the levels were
before and after. Prior revisions remain queryable forever. The methodology
version and composition that governed each revision remain attached to it.
---
## 14. Governance
- **Index committee:** two founders. The external seat is deliberately **open**
(see §0) and will be filled when the right person is found rather than for
appearance.
- **Methodology changes** are new versions with new hashes. Non-emergency
changes carry a public consultation period once the index is public.
- **Conflicts:** Philidor operates no product tracking PHIL10, and none is
planned for v1. Risk-assessment commercial relationships with constituents'
operators, where they exist, are disclosed as a category. The controlling
rule, which admits no exception: **money can buy coverage, custom products and
calculation services; it can never buy a risk score or a seat in a standard
index.**
- **Cessation:** if PHIL10 stops being calculated, that is announced with a
notice and the historical series remains published and verifiable.
---
## 15. Regulatory status
PHIL10 is private and unpublished, licensed to no one, and tracked by no
product. No regulatory-status claim is made in this version. A
counsel-reviewed benchmark statement is a prerequisite for public inception, not
for this document.
Nothing here is investment advice.
---
## 16. Known limitations
Stated exactly, because a rulebook that hides them is not worth publishing:
1. **The universe is small and concentrated.** Five names at glidepath start
(§5.1), drawn from a single-digit eligible set dominated by two protocols.
Caps (§6.1) and the constituent count are both set at glidepath levels for
exactly this reason, and the binding dimensions are published per
reconstitution.
2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is
measured; the horizon is not observable on-chain.
3. **Index deletion is not tracker realizability.** An extraordinary
reconstitution removes a name from the index; it does not assert that a
holder could have exited at that price, or at all.
4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps
NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic
loss looks implausible, so the close defers rather than recording it. This is
deliberate fail-closed behaviour and an open founder decision: a crisis
confirmation path is required before PHIL10 can claim to measure a crisis.
5. **No external methodology review** (§0).
6. **No public track record.** The series is preliminary and the soak is
private. Elapsed operating time cannot be simulated or shortened.
7. **Back-calculated history is a fixed-book reconstruction, not point-in-time
history** (§8.5, v1.3.0). Point-in-time eligibility is not reconstructable,
so the reconstruction holds the current book fixed and says so on every
observation. Selection history before inception does not exist and is not
claimed.
---
## 17. Version history
| Version | Date | Change |
| ------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. |
| 1.1.0 | 2026-08-03 | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key = no group, with curated-platform attribution failures excluded at eligibility; mechanism-attestation evidence path for the all-accruing gate (Spark). |
| 1.2.0 | 2026-08-03 | Constituent count N = 5 at glidepath start (census: 5 names clear every gate; target remains 10, each step back is a version — §5.1). |
| 1.3.0 | 2026-08-03 | Back-calculated history rules (§8.5): fixed-book reconstruction at pinned blocks, full pipeline + evidence, always labeled, scale-continuous anchoring, PPR basis disclosure. |
| 1.4.0 | 2026-08-04 | Aave v3 aToken adapter class: scaled-unit NAV from pool normalized income, identity anchoring, deficit fail-closed (§9.1); Aave withdrawability probe (§4.2); Aave accrual attestation (§4.1); count steps only at a reconstitution (§5.1). |
| Aave v3 aToken adapter class: scaled-unit NAV from pool normalized income, identity anchoring, deficit fail-closed (§9.1); Aave withdrawability probe (§4.2); Aave accrual attestation (§4.1); constituent count steps only at a reconstitution (§5.1). |
| 1.3.0 | 2026-08-03 | PHIL10 — Index Methodology sha256 afcd6b0ba4982671b76d79ef1a236f989c9373f596b272ac5b5bbd94d306ac04 Read the document (32 KB)# PHIL10 — Index Methodology **Index:** The Philidor Onchain Dollar Yield Index 10 **Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD **Methodology version:** 1.3.0 **Administrator:** Philidor Labs --- ## 0. Status of this document and of the index **PHIL10 is not an official benchmark and has no official inception date.** This document governs a **private operational soak**: the engine calculates a daily level from real on-chain data, on a real schedule, under real fail-closed rules, and every live observation it produces carries the status `preliminary` (reconstructed history carries `back_calculated` — §8.5). Nothing is published publicly, no product may track it, and the level series is not a track record. Two things follow, and they are stated here because a rulebook that overclaims is worse than none: 1. **Official inception is a separate, later act.** It requires a base date, a base value of 100.00, a public preliminary period, and the governance apparatus in §14 actually operating. Until then the series is a systems artefact, not a benchmark. 2. **No external methodology review has been performed.** The founders decided on 2026-07-22 to hold the external reviewer seat open until the right person is found rather than fill it for form's sake. Until that review exists, the compensating controls are: this document published in full, the dual-engine reconciliation of §9.4, the signed evidence of §9.5, and the honest limitations of §16. This document is versioned and content-hashed. The hash of the exact bytes of this file is recorded in `index_methodology_versions.content_hash`, and every composition and observation references the methodology version under which it was produced. --- ## 1. Objective PHIL10 is a rules-based, total-return index designed to measure a diversified set of risk-qualified, implementation-eligible USD-denominated onchain yield strategies. It answers one question: _what does a disciplined dollar allocator actually earn across the onchain venues that pass a real risk screen and can genuinely be entered and exited?_ It is deliberately **not** a market-coverage index. Breadth is not the goal; qualification is. Names beyond the constituent count (§5.1) are excluded on purpose, and the published bench (§7.4) states exactly which rule excluded each one. --- ## 2. Definitions | Term | Meaning in this document | | ------------------ | ----------------------------------------------------------------------------------------------------- | | **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. | | **Close** | The daily calculation producing one official level for one value date. | | **Constituent** | A vault included in the composition governing a value date. | | **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. | | **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). | | **NAV per share** | `convertToAssets(1 share)` read on-chain at the pinned close block. | | **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. | | **Observation** | One published (index, value date, revision) row with a level and a status. | | **Collection** | One complete run of the input collector, identified by a collection id. | --- ## 3. Universe A tracked vault is in the candidate universe if **all** of the following hold. Every exclusion carries a machine-readable reason, so the census can state why a name is out without a human re-deriving it. 1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`. 2. **Single-asset exposure.** A vault whose asset components list more than one asset (e.g. USDC/WETH) is excluded — it is not a dollar vault. 3. **Active and not shut down.** 4. **Chain is not held out.** Held-out chain ids are enumerated in code and currently comprise chain `9745`. 5. **The asset address is known.** Identity is (address, chain) everywhere downstream — FX feeds, adapters, caps. A candidate without an asset address cannot be carried honestly, so it is excluded rather than symbol-matched. **Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS, FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others enumerated in code. The list exists so the exclusion is reviewable, and so a new synthetic that slips past canonicalization is still caught by name. **Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to `circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and is treated as a distinct asset that nonetheless consumes the Tether issuer cap. --- ## 4. Eligibility A universe member must additionally pass **every** gate below. Order affects only which reason is reported first. | Gate | Threshold | | ------------------------- | ---------------------------------------------------------------------------- | | Risk vectors readable | Required — see fail-closed rule | | Hard-fail flag | Must be absent | | Depeg presumptive removal | Must be absent | | Incident clamp | Must be absent | | All-accruing | Required (v1 universe pays no distributions) | | Reviewed | Required | | Philidor risk score | ≥ **8.0** (Prime) | | Vault TVL | ≥ **$5,000,000** | | Vault age | ≥ **90 days** | | Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** | | Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** | | Stressed clip | ≤ **20%** of vault TVL | | FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain | The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a vault whose deposit asset cannot reach a price quorum on its chain is not priced conservatively, it cannot be priced **at all**, and including it would stop the index rather than degrade it. Independence is counted by oracle _family_, not by contract: two feeds from the same provider are one source. ### 4.1 The fail-closed rule **"We could not measure it" and "it passed" must never produce the same outcome.** A candidate whose liquidity test could not be executed, or whose risk vectors could not be read, is **ineligible** — it is never waved through. These are reported as distinct reasons (`liquidity_test_unavailable`, `risk_vectors_unavailable`) so the census can tell an unmeasurable name apart from an illiquid one. **All-accruing evidence (v1.1.0).** The all-accruing gate (§4) is evidenced by the ingestion pipeline's reward observations. Because an empty reward set is only informative when the pipeline demonstrably observes rewards for that protocol, a protocol with no recorded reward stream is normally _unverifiable_ — excluded, not passed. One documented exception exists: a **mechanism attestation**, a reviewed and provenance-carrying claim that the protocol's vault design structurally cannot distribute value outside NAV (recorded in code as `ACCRUAL_MECHANISM_ATTESTATIONS`, currently: Spark/Sky Savings tokens, whose yield accrues exclusively through the Savings Rate raising `convertToAssets`; reviewed 2026-08-03). An attestation substitutes only for the missing pipeline-observability signal. It never outranks a recorded reward stream, never bypasses evidence freshness, and never bypasses the `apr_net = base_apr + Σ rewards` decomposition cross-check — an attested protocol that starts paying incentives is caught by either surviving detector. ### 4.2 What the liquidity test measures, and what it assumes Stated plainly because the boundary is real: - **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both clip sizes, read on-chain at a pinned block. - **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which folds in the vault's currently available liquidity. - **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an underlying position unwinds, so tier-2 capacity is evaluated against total assets, which **assumes an orderly 7-day unwind**. The assumption is recorded in the signed evidence for every candidate so a reader sees it rather than infers it. This is a known limitation, restated in §16, and a live founder decision: either accept the orderly-unwind assumption or require real unwind evidence and exclude names that cannot supply it. --- ## 5. Selection 1. Rank all eligible candidates by the **total, data-driven ordering**: risk score descending, then vault age descending, then TVL descending, then ref_id ascending. Every tie-break is deterministic — a selection that could depend on map iteration order could not be reproduced, which would make the evidence chain worthless. 2. Take the top **N** (§5.1). 3. **Incumbency buffer.** An incumbent constituent is displaced only if the challenger beats it by **more than 0.2** of a risk score point **and** by **more than 3** rank places — both, strictly; clearing one alone retains the incumbent, and a challenger at exactly 0.2 points or exactly 3 ranks has not cleared it. (Corrected in v1.2.0: earlier versions of this document said "or", describing a rule the engine has never implemented — turnover must be clearly earned on both measures.) This suppresses churn from noise. The buffer is bypassed by extraordinary events (§12) — a hard-failed name leaves immediately. If fewer than N eligible names exist, the reconstitution is **infeasible** and reports why. PHIL10 does not publish an N-name index with N−1 names, and does not lower a gate to reach the number. ### 5.1 Constituent count (v1.2.0) **N = 5 at glidepath start. The target remains 10** — it is the index's name and its destination — and each step back toward it is a methodology version. This is the census speaking, not a preference. The first production census (2026-08-03) measured **5** names clearing every gate. The gap to 10 is not a tuning problem: the calculation engine prices ERC-4626 vaults only, which excludes rebasing money-market receipts (Aave aTokens, Compound Comet) regardless of their quality; reward-observability and executed-liquidity evidence exclude what cannot yet be measured; and the next nearest name enters by vault age in September 2026. The alternatives to reducing N were all worse: relaxing a gate (forbidden — §4.1), widening the universe into synthetic dollars (§3 excludes them by name, deliberately), or publishing nothing for months while a five-name book of measured, risk-qualified names sits idle. What a smaller N costs, stated plainly: less diversification per name (each constituent is 20% at target rather than 10%), and caps that bind harder (three same-protocol names are 60% of a five-name book). The §6.1 levels were re-checked against N = 5 on the measured census — the curator cap binds first (two same-curator names = 40% against 35%) and the waterfall's deterministic redistribution handles it. The count rises — 6, 7, … 10 — as names age in, measurement coverage widens, and scores move; each increase is a version bump justified by census evidence, exactly like a cap change. --- ## 6. Weighting **Equal weight**: each constituent's target is 1/N of the index, N per §5.1 (5 at glidepath start, target 10). The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75% safer than an 8.0, and score-weighting would make one estimate do two jobs, so a small scoring error would move both membership and capital. ### 6.1 Look-through caps Applied to the target weights by a deterministic cap-and-redistribution waterfall, on four dimensions: | Dimension | Cap | | --------- | ---- | | Protocol | 60% | | Issuer | 100% | | Curator | 35% | | Chain | 70% | Caps bind on the **look-through** dimension, not the vault name: two vaults on one protocol consume that protocol's cap jointly. Where a cap binds, weight is redistributed deterministically to uncapped names; the binding dimensions are recorded on the selection run. If the cap system cannot be satisfied, the reconstitution is infeasible and says so — caps are not quietly relaxed to force a result. **A null look-through key is membership in no group (v1.1.0).** A protocol-native vault (Aave, Spark, Compound, Yearn) has no curator: it belongs to no curator group and consumes no curator cap, in the trimming waterfall and in every verification of it alike. This is not a relaxation of the fail-closed rule — "there is no curator" is a measured fact about the vault's design, while "the curator is unknown where one should exist" is missing metadata, and missing metadata is an _eligibility_ exclusion decided before the waterfall ever runs (a curated-platform vault with no curator attribution is excluded as `curator_attribution_unavailable`). The same semantics apply to every cap dimension. **Cap levels are census-derived (v1.1.0).** The v1.0.0 levels (35/50/35/70) were set before any census had run against production. The first real census (2026-08-03, value date 2026-08-02) measured an eligible book that no 10-name equal-weight composition can satisfy under them: the measurable universe is Spark Savings and curated Morpho vaults in roughly equal number (each ~50% of a ten-name book against a 35% protocol cap), and 90–100% Circle-issued deposits (against a 50% issuer cap). A cap that admits no composition at all protects nothing. The v1.1.0 levels are the tightest caps the measured census satisfies with modest drift headroom: protocol 60%, issuer 100% (non-binding at glidepath start, stated plainly rather than pretended at), curator and chain unchanged. These remain a **glidepath**: they re-tighten as the eligible universe widens. Nothing re-tightens by itself — a 100% cap constrains nothing (weights always sum to exactly 100%, so the waterfall excludes such a dimension outright rather than letting rounding residue bind it) until a human lowers it, and like every cap change that takes a new methodology version with its own hash. Re-tightening the issuer cap is the first scheduled glidepath step once measurable non-Circle deposits exist, and each quarterly census is the standing occasion to take it. ### 6.2 Weight drift Between reconstitutions, weights **drift with performance**. They are not reset to target daily. Resetting daily would silently rebalance the index every day and publish a wrong level from day two onward — and both calculation engines would agree on it, because they would share the same malformed input. --- ## 7. Reconstitution ### 7.1 Schedule Scheduled reconstitutions are quarterly. A new composition is effective from a stated value date and governs closes **after** that date (§8.3). ### 7.2 Extraordinary reconstitution Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not apply. An index deletion is not a claim that a tracker could have exited at that price — see §16. ### 7.3 Evidence Every reconstitution records the full census: every candidate considered, every eligibility verdict with its reason, the ranking, the caps that bound, and the resulting composition — hashed and signed. ### 7.4 The bench The ranked eligible names that missed the cut are published with their rank. "The next four names and exactly which rule keeps each one out" is part of the product, not a byproduct. --- ## 8. Calculation The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md` (fixed-point representation, rounding, primitive operations, bounds). It governs where it is more specific than this section. ### 8.1 Constituent return For constituent _i_ over the interval ending at value date _t_: ``` r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1 ``` `D` is distributions. The v1 universe is all-accruing, so **D = 0 by construction** — yield accrues inside NAV per share. A vault that distributes is ineligible (§4) precisely so this term cannot be silently wrong. FX is a real measured price, not an assumed $1.00. A depeg therefore flows into the index level mechanically, as a loss, rather than being invisible. ### 8.2 Index level ``` L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t) ``` Chain-linking is the definition, not an approximation. Opening weights are the previous close's **drifted** weights (§6.2), never the composition targets — except on the first close after a reconstitution took effect, which is what a reconstitution means. ### 8.3 Reconstitution boundary A composition effective for value date D applies from D's close **forward**. The return _ending_ at D is computed under the **outgoing** composition; the new targets open the next interval. Applying the incoming composition to D would compute D's return over a constituent set that was not in force during it. ### 8.4 Gaps If the previous accepted close is more than one day earlier, the interval is a **multi-day return**, correctly labelled as such — never a silently mislabelled one-day return. A multi-day interval may not span a reconstitution boundary: if it would, the close defers rather than applying weights retroactively to days they did not govern. ### 8.5 Back-calculated history (v1.3.0) Pre-inception history MAY be reconstructed, under rules that keep it honest: 1. **The current book is held fixed.** A back-calculation clones the initial composition verbatim (reason `back_calc`) and reprices it at pinned, finalized historical blocks. It is NEVER a point-in-time re-selection: eligibility as of past dates is not reconstructible from recorded data (the Phase 0 finding), and pretending otherwise would be hindsight dressed as history. 2. **Same engine, same evidence.** Every reconstructed close runs the full production pipeline — sealed manifest, both engines, zero-tolerance reconciliation, signed exported evidence. 3. **Labeled, always.** Reconstructed observations carry `history_class = back_calculated` and that display status, regardless of any other state. They are never presented as live, and the publication target (lateness) does not apply to them. 4. **Scale-continuous, never restating.** The reconstructed segment is anchored so that its final level times the TRUE boundary return (computed target-weighted from the segment-end collection and the first live close's sealed inputs) equals the live base, to within a stated rounding residual. The live chain — including the first live close's inception zero return — is never modified; acceptance is terminal. 5. **PPR basis disclosure.** A PPR fixing whose window includes reconstructed observations states so (`basis` on the fixing): the rate is real arithmetic over a partially reconstructed series, and the reader decides what that is worth. Endpoints are still never substituted. ### 8.6 Precision Internal arithmetic is scaled integer at 8 decimal places with half-even rounding at defined points only. Published levels are stated at 2 decimal places. Value date, calculation timestamp and publication timestamp are distinct fields and are never conflated. --- ## 9. Data, provenance and verification ### 9.1 NAV `convertToAssets(1 share)` read on-chain at a **pinned block** per chain, after that chain's finality rule is satisfied. Before the read is accepted: `asset()` must still bind to the expected deposit asset; `totalSupply()` must be non-zero; the resulting NAV must be plausible; and a move beyond **500 bps** from the previous accepted NAV is **rejected**, not clamped — a clamped absurd input produces a plausible wrong number, the failure a benchmark can least afford. Share and asset decimals are **probed on-chain at registration** and persisted. They are never defaulted: a vault without probed conformance is not priced, the collection is therefore incomplete, and the close defers. ### 9.2 FX Push oracles only, from the families `chainlink`, `chronicle`, `redstone`, `api3`. The registry is keyed by **token address + chain**, never by symbol — symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark. The published FX is the **median of the responsive quorum**. A quote more than 200 bps from that median is **flagged and still counted** — it is not discarded. That is deliberate, and worth stating plainly because the intuitive rule is the opposite. Discarding a quote requires deciding it is wrong, and the median is already robust to a single bad source without that decision. More importantly, exclusion would make aggregation depend on a _prior pass's_ labels: replaying the stored evidence for a past close could then produce a different number from the one published, which would make the evidence package unverifiable. Flagging records the disagreement in the evidence without letting it change the arithmetic. Independence is counted by **oracle family**, and a single feed address may not be registered under more than one family — quorum is a claim about independent sources, not about rows. **A known dependency, stated because it is invisible otherwise.** Chronicle's mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller except a short allowlist, which includes the zero address. PHIL10 reads them as an off-chain indexer via `eth_call` with no `from`, which defaults to the zero address, so the reads succeed — but that permission is Chronicle's to revoke. If it were revoked, those quotes would begin erroring rather than returning a wrong number, the affected assets would fall from three responsive sources to two, and pricing would continue in a recorded degraded state. The failure mode is therefore visible and safe, but the dependency is real and is not something PHIL10 controls. Losing quorum does not produce a price: it produces a recorded degraded state with a reason. An asset with fewer than three independent feeds is a founder decision, not something the collector works around: such an asset is excluded from the universe by the FX-quorum gate (§4) rather than silently priced. ### 9.3 Collection coherence Every input row is stamped with a collection id. A completeness sentinel is written **last**, and only when every constituent produced both a NAV and a median. A crashed or partial collection leaves no sentinel and is never consumed — the close reads the last complete collection, or defers. ### 9.4 Dual-engine reconciliation Every close is computed twice: a primary scaled-integer engine in TypeScript and an independent engine in PostgreSQL `numeric`, over the **same sealed inputs** but on a different arithmetic substrate. Agreement is required at **zero tolerance** on the level, the daily return, each constituent return and each close weight. Disagreement **blocks publication**; it does not average, pick a side, or warn. ### 9.5 Evidence Every close emits a signed evidence package: the sealed inputs, both engines' results, the reconciliation, the governing composition and methodology version, engine versions and hashes. Signatures are Ed25519; the public half of every signing key is registered in an append-only registry before use, so historical signatures remain verifiable across key rotation. ### 9.6 Append-only Observations, inputs, runs and evidence are **insert-only**, enforced by database triggers, including protection against TRUNCATE. A correction is a new revision plus a notice (§13). History is never edited. --- ## 10. Staleness ladder and statuses | Input age at close | Effect | | ------------------ | --------------------------------------------------------- | | ≤ 6h | Normal | | > 6h | Constituent flagged; close proceeds | | > 48h | Close proceeds, status records calculation on stale input | | > 72h | **Close is `not_calculated`** | A single constituent past 72h makes the whole close `not_calculated`. Constituents are **never dropped and renormalized to rescue a close** — that would silently change the composition on precisely the days the data is worst. A carried-forward annualized rate is never accrued. **Status vocabulary** (fixed; these exact words appear in the API): `preliminary`, `official`, `revised`, `delayed`, `insufficient_data`, `not_calculated`, `back_calculated`. An honest gap is **permanent**: once a later close has been accepted, a skipped date is not retroactively filled, because doing so would break the internal chaining of an already-signed series. --- ## 11. Publication Closes are calculated after the value date's close instant and after chain finality. The target publication time is 16:30 UTC. A late close is published late and labelled, never backdated. A close that cannot be computed is recorded with the reason — silence is not a permitted outcome, and a dead-man's watchdog alerts if a value date passes with no observation. --- ## 12. Depeg ladder Evaluated on the deposit asset against a two-source-minimum quorum: | Condition | Action | | --------------------------- | -------------------------------------------- | | < $0.985 for 4 hours | Review flagged | | < $0.97 for 15 minutes | Extraordinary review flagged | | < $0.95, quorum-confirmed | **Presumptive removal** | | < $0.95, single source only | Extraordinary flagged (removal needs quorum) | Flags annotate a close; they never block it. Severity is **monotonic within an open episode** — it can only rise. It clears only through the quorum-guarded recovery exit that closes the episode; a single low-confidence tick can never downgrade a confirmed removal and re-admit a still-depegged vault. A depeg is also visible in the level itself, because FX is measured (§8.1). --- ## 13. Corrections and restatement An error is corrected by **new revisions plus a numbered public notice** stating what changed, why, which value dates are affected and what the levels were before and after. Prior revisions remain queryable forever. The methodology version and composition that governed each revision remain attached to it. --- ## 14. Governance - **Index committee:** two founders. The external seat is deliberately **open** (see §0) and will be filled when the right person is found rather than for appearance. - **Methodology changes** are new versions with new hashes. Non-emergency changes carry a public consultation period once the index is public. - **Conflicts:** Philidor operates no product tracking PHIL10, and none is planned for v1. Risk-assessment commercial relationships with constituents' operators, where they exist, are disclosed as a category. The controlling rule, which admits no exception: **money can buy coverage, custom products and calculation services; it can never buy a risk score or a seat in a standard index.** - **Cessation:** if PHIL10 stops being calculated, that is announced with a notice and the historical series remains published and verifiable. --- ## 15. Regulatory status PHIL10 is private and unpublished, licensed to no one, and tracked by no product. No regulatory-status claim is made in this version. A counsel-reviewed benchmark statement is a prerequisite for public inception, not for this document. Nothing here is investment advice. --- ## 16. Known limitations Stated exactly, because a rulebook that hides them is not worth publishing: 1. **The universe is small and concentrated.** Five names at glidepath start (§5.1), drawn from a single-digit eligible set dominated by two protocols. Caps (§6.1) and the constituent count are both set at glidepath levels for exactly this reason, and the binding dimensions are published per reconstitution. 2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is measured; the horizon is not observable on-chain. 3. **Index deletion is not tracker realizability.** An extraordinary reconstitution removes a name from the index; it does not assert that a holder could have exited at that price, or at all. 4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic loss looks implausible, so the close defers rather than recording it. This is deliberate fail-closed behaviour and an open founder decision: a crisis confirmation path is required before PHIL10 can claim to measure a crisis. 5. **No external methodology review** (§0). 6. **No public track record.** The series is preliminary and the soak is private. Elapsed operating time cannot be simulated or shortened. 7. **Back-calculated history is a fixed-book reconstruction, not point-in-time history** (§8.5, v1.3.0). Point-in-time eligibility is not reconstructable, so the reconstruction holds the current book fixed and says so on every observation. Selection history before inception does not exist and is not claimed. --- ## 17. Version history | Version | Date | Change | | ------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. | | 1.1.0 | 2026-08-03 | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key = no group, with curated-platform attribution failures excluded at eligibility; mechanism-attestation evidence path for the all-accruing gate (Spark). | | 1.2.0 | 2026-08-03 | Constituent count N = 5 at glidepath start (census: 5 names clear every gate; target remains 10, each step back is a version — §5.1). | | 1.3.0 | 2026-08-03 | Back-calculated history rules (§8.5): fixed-book reconstruction at pinned blocks, full pipeline + evidence, always labeled, scale-continuous anchoring, PPR basis disclosure. | | Back-calculated history rules (§8.5): fixed-book reconstruction at pinned blocks, full pipeline and evidence, always labeled, scale-continuous anchoring, PPR basis disclosure. |
| 1.2.0 | 2026-08-03 | PHIL10 — Index Methodology sha256 3edeee2c809afa7fa3c4daf9b98e3ad23ebd70f381be4854f92438d20cfd8c40 Read the document (30 KB)# PHIL10 — Index Methodology **Index:** The Philidor Onchain Dollar Yield Index 10 **Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD **Methodology version:** 1.2.0 **Administrator:** Philidor Labs --- ## 0. Status of this document and of the index **PHIL10 is not an official benchmark and has no official inception date.** This document governs a **private operational soak**: the engine calculates a daily level from real on-chain data, on a real schedule, under real fail-closed rules, and every observation it produces carries the status `preliminary`. Nothing is published publicly, no product may track it, and the level series is not a track record. Two things follow, and they are stated here because a rulebook that overclaims is worse than none: 1. **Official inception is a separate, later act.** It requires a base date, a base value of 100.00, a public preliminary period, and the governance apparatus in §14 actually operating. Until then the series is a systems artefact, not a benchmark. 2. **No external methodology review has been performed.** The founders decided on 2026-07-22 to hold the external reviewer seat open until the right person is found rather than fill it for form's sake. Until that review exists, the compensating controls are: this document published in full, the dual-engine reconciliation of §9.4, the signed evidence of §9.5, and the honest limitations of §16. This document is versioned and content-hashed. The hash of the exact bytes of this file is recorded in `index_methodology_versions.content_hash`, and every composition and observation references the methodology version under which it was produced. --- ## 1. Objective PHIL10 is a rules-based, total-return index designed to measure a diversified set of risk-qualified, implementation-eligible USD-denominated onchain yield strategies. It answers one question: _what does a disciplined dollar allocator actually earn across the onchain venues that pass a real risk screen and can genuinely be entered and exited?_ It is deliberately **not** a market-coverage index. Breadth is not the goal; qualification is. Names beyond the constituent count (§5.1) are excluded on purpose, and the published bench (§7.4) states exactly which rule excluded each one. --- ## 2. Definitions | Term | Meaning in this document | | ------------------ | ----------------------------------------------------------------------------------------------------- | | **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. | | **Close** | The daily calculation producing one official level for one value date. | | **Constituent** | A vault included in the composition governing a value date. | | **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. | | **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). | | **NAV per share** | `convertToAssets(1 share)` read on-chain at the pinned close block. | | **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. | | **Observation** | One published (index, value date, revision) row with a level and a status. | | **Collection** | One complete run of the input collector, identified by a collection id. | --- ## 3. Universe A tracked vault is in the candidate universe if **all** of the following hold. Every exclusion carries a machine-readable reason, so the census can state why a name is out without a human re-deriving it. 1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`. 2. **Single-asset exposure.** A vault whose asset components list more than one asset (e.g. USDC/WETH) is excluded — it is not a dollar vault. 3. **Active and not shut down.** 4. **Chain is not held out.** Held-out chain ids are enumerated in code and currently comprise chain `9745`. 5. **The asset address is known.** Identity is (address, chain) everywhere downstream — FX feeds, adapters, caps. A candidate without an asset address cannot be carried honestly, so it is excluded rather than symbol-matched. **Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS, FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others enumerated in code. The list exists so the exclusion is reviewable, and so a new synthetic that slips past canonicalization is still caught by name. **Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to `circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and is treated as a distinct asset that nonetheless consumes the Tether issuer cap. --- ## 4. Eligibility A universe member must additionally pass **every** gate below. Order affects only which reason is reported first. | Gate | Threshold | | ------------------------- | ---------------------------------------------------------------------------- | | Risk vectors readable | Required — see fail-closed rule | | Hard-fail flag | Must be absent | | Depeg presumptive removal | Must be absent | | Incident clamp | Must be absent | | All-accruing | Required (v1 universe pays no distributions) | | Reviewed | Required | | Philidor risk score | ≥ **8.0** (Prime) | | Vault TVL | ≥ **$5,000,000** | | Vault age | ≥ **90 days** | | Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** | | Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** | | Stressed clip | ≤ **20%** of vault TVL | | FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain | The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a vault whose deposit asset cannot reach a price quorum on its chain is not priced conservatively, it cannot be priced **at all**, and including it would stop the index rather than degrade it. Independence is counted by oracle _family_, not by contract: two feeds from the same provider are one source. ### 4.1 The fail-closed rule **"We could not measure it" and "it passed" must never produce the same outcome.** A candidate whose liquidity test could not be executed, or whose risk vectors could not be read, is **ineligible** — it is never waved through. These are reported as distinct reasons (`liquidity_test_unavailable`, `risk_vectors_unavailable`) so the census can tell an unmeasurable name apart from an illiquid one. **All-accruing evidence (v1.1.0).** The all-accruing gate (§4) is evidenced by the ingestion pipeline's reward observations. Because an empty reward set is only informative when the pipeline demonstrably observes rewards for that protocol, a protocol with no recorded reward stream is normally _unverifiable_ — excluded, not passed. One documented exception exists: a **mechanism attestation**, a reviewed and provenance-carrying claim that the protocol's vault design structurally cannot distribute value outside NAV (recorded in code as `ACCRUAL_MECHANISM_ATTESTATIONS`, currently: Spark/Sky Savings tokens, whose yield accrues exclusively through the Savings Rate raising `convertToAssets`; reviewed 2026-08-03). An attestation substitutes only for the missing pipeline-observability signal. It never outranks a recorded reward stream, never bypasses evidence freshness, and never bypasses the `apr_net = base_apr + Σ rewards` decomposition cross-check — an attested protocol that starts paying incentives is caught by either surviving detector. ### 4.2 What the liquidity test measures, and what it assumes Stated plainly because the boundary is real: - **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both clip sizes, read on-chain at a pinned block. - **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which folds in the vault's currently available liquidity. - **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an underlying position unwinds, so tier-2 capacity is evaluated against total assets, which **assumes an orderly 7-day unwind**. The assumption is recorded in the signed evidence for every candidate so a reader sees it rather than infers it. This is a known limitation, restated in §16, and a live founder decision: either accept the orderly-unwind assumption or require real unwind evidence and exclude names that cannot supply it. --- ## 5. Selection 1. Rank all eligible candidates by the **total, data-driven ordering**: risk score descending, then vault age descending, then TVL descending, then ref_id ascending. Every tie-break is deterministic — a selection that could depend on map iteration order could not be reproduced, which would make the evidence chain worthless. 2. Take the top **N** (§5.1). 3. **Incumbency buffer.** An incumbent constituent is displaced only if the challenger beats it by **more than 0.2** of a risk score point **and** by **more than 3** rank places — both, strictly; clearing one alone retains the incumbent, and a challenger at exactly 0.2 points or exactly 3 ranks has not cleared it. (Corrected in v1.2.0: earlier versions of this document said "or", describing a rule the engine has never implemented — turnover must be clearly earned on both measures.) This suppresses churn from noise. The buffer is bypassed by extraordinary events (§12) — a hard-failed name leaves immediately. If fewer than N eligible names exist, the reconstitution is **infeasible** and reports why. PHIL10 does not publish an N-name index with N−1 names, and does not lower a gate to reach the number. ### 5.1 Constituent count (v1.2.0) **N = 5 at glidepath start. The target remains 10** — it is the index's name and its destination — and each step back toward it is a methodology version. This is the census speaking, not a preference. The first production census (2026-08-03) measured **5** names clearing every gate. The gap to 10 is not a tuning problem: the calculation engine prices ERC-4626 vaults only, which excludes rebasing money-market receipts (Aave aTokens, Compound Comet) regardless of their quality; reward-observability and executed-liquidity evidence exclude what cannot yet be measured; and the next nearest name enters by vault age in September 2026. The alternatives to reducing N were all worse: relaxing a gate (forbidden — §4.1), widening the universe into synthetic dollars (§3 excludes them by name, deliberately), or publishing nothing for months while a five-name book of measured, risk-qualified names sits idle. What a smaller N costs, stated plainly: less diversification per name (each constituent is 20% at target rather than 10%), and caps that bind harder (three same-protocol names are 60% of a five-name book). The §6.1 levels were re-checked against N = 5 on the measured census — the curator cap binds first (two same-curator names = 40% against 35%) and the waterfall's deterministic redistribution handles it. The count rises — 6, 7, … 10 — as names age in, measurement coverage widens, and scores move; each increase is a version bump justified by census evidence, exactly like a cap change. --- ## 6. Weighting **Equal weight**: each constituent's target is 1/N of the index, N per §5.1 (5 at glidepath start, target 10). The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75% safer than an 8.0, and score-weighting would make one estimate do two jobs, so a small scoring error would move both membership and capital. ### 6.1 Look-through caps Applied to the target weights by a deterministic cap-and-redistribution waterfall, on four dimensions: | Dimension | Cap | | --------- | ---- | | Protocol | 60% | | Issuer | 100% | | Curator | 35% | | Chain | 70% | Caps bind on the **look-through** dimension, not the vault name: two vaults on one protocol consume that protocol's cap jointly. Where a cap binds, weight is redistributed deterministically to uncapped names; the binding dimensions are recorded on the selection run. If the cap system cannot be satisfied, the reconstitution is infeasible and says so — caps are not quietly relaxed to force a result. **A null look-through key is membership in no group (v1.1.0).** A protocol-native vault (Aave, Spark, Compound, Yearn) has no curator: it belongs to no curator group and consumes no curator cap, in the trimming waterfall and in every verification of it alike. This is not a relaxation of the fail-closed rule — "there is no curator" is a measured fact about the vault's design, while "the curator is unknown where one should exist" is missing metadata, and missing metadata is an _eligibility_ exclusion decided before the waterfall ever runs (a curated-platform vault with no curator attribution is excluded as `curator_attribution_unavailable`). The same semantics apply to every cap dimension. **Cap levels are census-derived (v1.1.0).** The v1.0.0 levels (35/50/35/70) were set before any census had run against production. The first real census (2026-08-03, value date 2026-08-02) measured an eligible book that no 10-name equal-weight composition can satisfy under them: the measurable universe is Spark Savings and curated Morpho vaults in roughly equal number (each ~50% of a ten-name book against a 35% protocol cap), and 90–100% Circle-issued deposits (against a 50% issuer cap). A cap that admits no composition at all protects nothing. The v1.1.0 levels are the tightest caps the measured census satisfies with modest drift headroom: protocol 60%, issuer 100% (non-binding at glidepath start, stated plainly rather than pretended at), curator and chain unchanged. These remain a **glidepath**: they re-tighten as the eligible universe widens. Nothing re-tightens by itself — a 100% cap constrains nothing (weights always sum to exactly 100%, so the waterfall excludes such a dimension outright rather than letting rounding residue bind it) until a human lowers it, and like every cap change that takes a new methodology version with its own hash. Re-tightening the issuer cap is the first scheduled glidepath step once measurable non-Circle deposits exist, and each quarterly census is the standing occasion to take it. ### 6.2 Weight drift Between reconstitutions, weights **drift with performance**. They are not reset to target daily. Resetting daily would silently rebalance the index every day and publish a wrong level from day two onward — and both calculation engines would agree on it, because they would share the same malformed input. --- ## 7. Reconstitution ### 7.1 Schedule Scheduled reconstitutions are quarterly. A new composition is effective from a stated value date and governs closes **after** that date (§8.3). ### 7.2 Extraordinary reconstitution Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not apply. An index deletion is not a claim that a tracker could have exited at that price — see §16. ### 7.3 Evidence Every reconstitution records the full census: every candidate considered, every eligibility verdict with its reason, the ranking, the caps that bound, and the resulting composition — hashed and signed. ### 7.4 The bench The ranked eligible names that missed the cut are published with their rank. "The next four names and exactly which rule keeps each one out" is part of the product, not a byproduct. --- ## 8. Calculation The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md` (fixed-point representation, rounding, primitive operations, bounds). It governs where it is more specific than this section. ### 8.1 Constituent return For constituent _i_ over the interval ending at value date _t_: ``` r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1 ``` `D` is distributions. The v1 universe is all-accruing, so **D = 0 by construction** — yield accrues inside NAV per share. A vault that distributes is ineligible (§4) precisely so this term cannot be silently wrong. FX is a real measured price, not an assumed $1.00. A depeg therefore flows into the index level mechanically, as a loss, rather than being invisible. ### 8.2 Index level ``` L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t) ``` Chain-linking is the definition, not an approximation. Opening weights are the previous close's **drifted** weights (§6.2), never the composition targets — except on the first close after a reconstitution took effect, which is what a reconstitution means. ### 8.3 Reconstitution boundary A composition effective for value date D applies from D's close **forward**. The return _ending_ at D is computed under the **outgoing** composition; the new targets open the next interval. Applying the incoming composition to D would compute D's return over a constituent set that was not in force during it. ### 8.4 Gaps If the previous accepted close is more than one day earlier, the interval is a **multi-day return**, correctly labelled as such — never a silently mislabelled one-day return. A multi-day interval may not span a reconstitution boundary: if it would, the close defers rather than applying weights retroactively to days they did not govern. ### 8.5 Precision Internal arithmetic is scaled integer at 8 decimal places with half-even rounding at defined points only. Published levels are stated at 2 decimal places. Value date, calculation timestamp and publication timestamp are distinct fields and are never conflated. --- ## 9. Data, provenance and verification ### 9.1 NAV `convertToAssets(1 share)` read on-chain at a **pinned block** per chain, after that chain's finality rule is satisfied. Before the read is accepted: `asset()` must still bind to the expected deposit asset; `totalSupply()` must be non-zero; the resulting NAV must be plausible; and a move beyond **500 bps** from the previous accepted NAV is **rejected**, not clamped — a clamped absurd input produces a plausible wrong number, the failure a benchmark can least afford. Share and asset decimals are **probed on-chain at registration** and persisted. They are never defaulted: a vault without probed conformance is not priced, the collection is therefore incomplete, and the close defers. ### 9.2 FX Push oracles only, from the families `chainlink`, `chronicle`, `redstone`, `api3`. The registry is keyed by **token address + chain**, never by symbol — symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark. The published FX is the **median of the responsive quorum**. A quote more than 200 bps from that median is **flagged and still counted** — it is not discarded. That is deliberate, and worth stating plainly because the intuitive rule is the opposite. Discarding a quote requires deciding it is wrong, and the median is already robust to a single bad source without that decision. More importantly, exclusion would make aggregation depend on a _prior pass's_ labels: replaying the stored evidence for a past close could then produce a different number from the one published, which would make the evidence package unverifiable. Flagging records the disagreement in the evidence without letting it change the arithmetic. Independence is counted by **oracle family**, and a single feed address may not be registered under more than one family — quorum is a claim about independent sources, not about rows. **A known dependency, stated because it is invisible otherwise.** Chronicle's mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller except a short allowlist, which includes the zero address. PHIL10 reads them as an off-chain indexer via `eth_call` with no `from`, which defaults to the zero address, so the reads succeed — but that permission is Chronicle's to revoke. If it were revoked, those quotes would begin erroring rather than returning a wrong number, the affected assets would fall from three responsive sources to two, and pricing would continue in a recorded degraded state. The failure mode is therefore visible and safe, but the dependency is real and is not something PHIL10 controls. Losing quorum does not produce a price: it produces a recorded degraded state with a reason. An asset with fewer than three independent feeds is a founder decision, not something the collector works around: such an asset is excluded from the universe by the FX-quorum gate (§4) rather than silently priced. ### 9.3 Collection coherence Every input row is stamped with a collection id. A completeness sentinel is written **last**, and only when every constituent produced both a NAV and a median. A crashed or partial collection leaves no sentinel and is never consumed — the close reads the last complete collection, or defers. ### 9.4 Dual-engine reconciliation Every close is computed twice: a primary scaled-integer engine in TypeScript and an independent engine in PostgreSQL `numeric`, over the **same sealed inputs** but on a different arithmetic substrate. Agreement is required at **zero tolerance** on the level, the daily return, each constituent return and each close weight. Disagreement **blocks publication**; it does not average, pick a side, or warn. ### 9.5 Evidence Every close emits a signed evidence package: the sealed inputs, both engines' results, the reconciliation, the governing composition and methodology version, engine versions and hashes. Signatures are Ed25519; the public half of every signing key is registered in an append-only registry before use, so historical signatures remain verifiable across key rotation. ### 9.6 Append-only Observations, inputs, runs and evidence are **insert-only**, enforced by database triggers, including protection against TRUNCATE. A correction is a new revision plus a notice (§13). History is never edited. --- ## 10. Staleness ladder and statuses | Input age at close | Effect | | ------------------ | --------------------------------------------------------- | | ≤ 6h | Normal | | > 6h | Constituent flagged; close proceeds | | > 48h | Close proceeds, status records calculation on stale input | | > 72h | **Close is `not_calculated`** | A single constituent past 72h makes the whole close `not_calculated`. Constituents are **never dropped and renormalized to rescue a close** — that would silently change the composition on precisely the days the data is worst. A carried-forward annualized rate is never accrued. **Status vocabulary** (fixed; these exact words appear in the API): `preliminary`, `official`, `revised`, `delayed`, `insufficient_data`, `not_calculated`, `back_calculated`. An honest gap is **permanent**: once a later close has been accepted, a skipped date is not retroactively filled, because doing so would break the internal chaining of an already-signed series. --- ## 11. Publication Closes are calculated after the value date's close instant and after chain finality. The target publication time is 16:30 UTC. A late close is published late and labelled, never backdated. A close that cannot be computed is recorded with the reason — silence is not a permitted outcome, and a dead-man's watchdog alerts if a value date passes with no observation. --- ## 12. Depeg ladder Evaluated on the deposit asset against a two-source-minimum quorum: | Condition | Action | | --------------------------- | -------------------------------------------- | | < $0.985 for 4 hours | Review flagged | | < $0.97 for 15 minutes | Extraordinary review flagged | | < $0.95, quorum-confirmed | **Presumptive removal** | | < $0.95, single source only | Extraordinary flagged (removal needs quorum) | Flags annotate a close; they never block it. Severity is **monotonic within an open episode** — it can only rise. It clears only through the quorum-guarded recovery exit that closes the episode; a single low-confidence tick can never downgrade a confirmed removal and re-admit a still-depegged vault. A depeg is also visible in the level itself, because FX is measured (§8.1). --- ## 13. Corrections and restatement An error is corrected by **new revisions plus a numbered public notice** stating what changed, why, which value dates are affected and what the levels were before and after. Prior revisions remain queryable forever. The methodology version and composition that governed each revision remain attached to it. --- ## 14. Governance - **Index committee:** two founders. The external seat is deliberately **open** (see §0) and will be filled when the right person is found rather than for appearance. - **Methodology changes** are new versions with new hashes. Non-emergency changes carry a public consultation period once the index is public. - **Conflicts:** Philidor operates no product tracking PHIL10, and none is planned for v1. Risk-assessment commercial relationships with constituents' operators, where they exist, are disclosed as a category. The controlling rule, which admits no exception: **money can buy coverage, custom products and calculation services; it can never buy a risk score or a seat in a standard index.** - **Cessation:** if PHIL10 stops being calculated, that is announced with a notice and the historical series remains published and verifiable. --- ## 15. Regulatory status PHIL10 is private and unpublished, licensed to no one, and tracked by no product. No regulatory-status claim is made in this version. A counsel-reviewed benchmark statement is a prerequisite for public inception, not for this document. Nothing here is investment advice. --- ## 16. Known limitations Stated exactly, because a rulebook that hides them is not worth publishing: 1. **The universe is small and concentrated.** Five names at glidepath start (§5.1), drawn from a single-digit eligible set dominated by two protocols. Caps (§6.1) and the constituent count are both set at glidepath levels for exactly this reason, and the binding dimensions are published per reconstitution. 2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is measured; the horizon is not observable on-chain. 3. **Index deletion is not tracker realizability.** An extraordinary reconstitution removes a name from the index; it does not assert that a holder could have exited at that price, or at all. 4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic loss looks implausible, so the close defers rather than recording it. This is deliberate fail-closed behaviour and an open founder decision: a crisis confirmation path is required before PHIL10 can claim to measure a crisis. 5. **No external methodology review** (§0). 6. **No public track record.** The series is preliminary and the soak is private. Elapsed operating time cannot be simulated or shortened. 7. **No back-calculated history is published in v1.** Point-in-time score history is not reconstructable far enough back to do it honestly. --- ## 17. Version history | Version | Date | Change | | ------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. | | 1.1.0 | 2026-08-03 | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key = no group, with curated-platform attribution failures excluded at eligibility; mechanism-attestation evidence path for the all-accruing gate (Spark). | | 1.2.0 | 2026-08-03 | Constituent count N = 5 at glidepath start (census: 5 names clear every gate; target remains 10, each step back is a version — §5.1). | | Constituent count N = 5 at glidepath start (census: 5 names clear every gate; target remains 10, each step back is a version). |
| 1.1.0 | 2026-08-03 | PHIL10 — Index Methodology sha256 f09cbb9b42fb33452c50b9dcfd61b2198982286f57716de0b1c19e7e0fef49af Read the document (28 KB)# PHIL10 — Index Methodology **Index:** The Philidor Onchain Dollar Yield Index 10 **Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD **Methodology version:** 1.1.0 **Administrator:** Philidor Labs --- ## 0. Status of this document and of the index **PHIL10 is not an official benchmark and has no official inception date.** This document governs a **private operational soak**: the engine calculates a daily level from real on-chain data, on a real schedule, under real fail-closed rules, and every observation it produces carries the status `preliminary`. Nothing is published publicly, no product may track it, and the level series is not a track record. Two things follow, and they are stated here because a rulebook that overclaims is worse than none: 1. **Official inception is a separate, later act.** It requires a base date, a base value of 100.00, a public preliminary period, and the governance apparatus in §14 actually operating. Until then the series is a systems artefact, not a benchmark. 2. **No external methodology review has been performed.** The founders decided on 2026-07-22 to hold the external reviewer seat open until the right person is found rather than fill it for form's sake. Until that review exists, the compensating controls are: this document published in full, the dual-engine reconciliation of §9.4, the signed evidence of §9.5, and the honest limitations of §16. This document is versioned and content-hashed. The hash of the exact bytes of this file is recorded in `index_methodology_versions.content_hash`, and every composition and observation references the methodology version under which it was produced. --- ## 1. Objective PHIL10 is a rules-based, total-return index designed to measure a diversified set of risk-qualified, implementation-eligible USD-denominated onchain yield strategies. It answers one question: _what does a disciplined dollar allocator actually earn across the onchain venues that pass a real risk screen and can genuinely be entered and exited?_ It is deliberately **not** a market-coverage index. Breadth is not the goal; qualification is. Names 11 and beyond are excluded on purpose, and the published bench (§7.4) states exactly which rule excluded each one. --- ## 2. Definitions | Term | Meaning in this document | | ------------------ | ----------------------------------------------------------------------------------------------------- | | **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. | | **Close** | The daily calculation producing one official level for one value date. | | **Constituent** | A vault included in the composition governing a value date. | | **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. | | **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). | | **NAV per share** | `convertToAssets(1 share)` read on-chain at the pinned close block. | | **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. | | **Observation** | One published (index, value date, revision) row with a level and a status. | | **Collection** | One complete run of the input collector, identified by a collection id. | --- ## 3. Universe A tracked vault is in the candidate universe if **all** of the following hold. Every exclusion carries a machine-readable reason, so the census can state why a name is out without a human re-deriving it. 1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`. 2. **Single-asset exposure.** A vault whose asset components list more than one asset (e.g. USDC/WETH) is excluded — it is not a dollar vault. 3. **Active and not shut down.** 4. **Chain is not held out.** Held-out chain ids are enumerated in code and currently comprise chain `9745`. 5. **The asset address is known.** Identity is (address, chain) everywhere downstream — FX feeds, adapters, caps. A candidate without an asset address cannot be carried honestly, so it is excluded rather than symbol-matched. **Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS, FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others enumerated in code. The list exists so the exclusion is reviewable, and so a new synthetic that slips past canonicalization is still caught by name. **Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to `circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and is treated as a distinct asset that nonetheless consumes the Tether issuer cap. --- ## 4. Eligibility A universe member must additionally pass **every** gate below. Order affects only which reason is reported first. | Gate | Threshold | | ------------------------- | ---------------------------------------------------------------------------- | | Risk vectors readable | Required — see fail-closed rule | | Hard-fail flag | Must be absent | | Depeg presumptive removal | Must be absent | | Incident clamp | Must be absent | | All-accruing | Required (v1 universe pays no distributions) | | Reviewed | Required | | Philidor risk score | ≥ **8.0** (Prime) | | Vault TVL | ≥ **$5,000,000** | | Vault age | ≥ **90 days** | | Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** | | Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** | | Stressed clip | ≤ **20%** of vault TVL | | FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain | The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a vault whose deposit asset cannot reach a price quorum on its chain is not priced conservatively, it cannot be priced **at all**, and including it would stop the index rather than degrade it. Independence is counted by oracle _family_, not by contract: two feeds from the same provider are one source. ### 4.1 The fail-closed rule **"We could not measure it" and "it passed" must never produce the same outcome.** A candidate whose liquidity test could not be executed, or whose risk vectors could not be read, is **ineligible** — it is never waved through. These are reported as distinct reasons (`liquidity_test_unavailable`, `risk_vectors_unavailable`) so the census can tell an unmeasurable name apart from an illiquid one. **All-accruing evidence (v1.1.0).** The all-accruing gate (§4) is evidenced by the ingestion pipeline's reward observations. Because an empty reward set is only informative when the pipeline demonstrably observes rewards for that protocol, a protocol with no recorded reward stream is normally _unverifiable_ — excluded, not passed. One documented exception exists: a **mechanism attestation**, a reviewed and provenance-carrying claim that the protocol's vault design structurally cannot distribute value outside NAV (recorded in code as `ACCRUAL_MECHANISM_ATTESTATIONS`, currently: Spark/Sky Savings tokens, whose yield accrues exclusively through the Savings Rate raising `convertToAssets`; reviewed 2026-08-03). An attestation substitutes only for the missing pipeline-observability signal. It never outranks a recorded reward stream, never bypasses evidence freshness, and never bypasses the `apr_net = base_apr + Σ rewards` decomposition cross-check — an attested protocol that starts paying incentives is caught by either surviving detector. ### 4.2 What the liquidity test measures, and what it assumes Stated plainly because the boundary is real: - **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both clip sizes, read on-chain at a pinned block. - **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which folds in the vault's currently available liquidity. - **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an underlying position unwinds, so tier-2 capacity is evaluated against total assets, which **assumes an orderly 7-day unwind**. The assumption is recorded in the signed evidence for every candidate so a reader sees it rather than infers it. This is a known limitation, restated in §16, and a live founder decision: either accept the orderly-unwind assumption or require real unwind evidence and exclude names that cannot supply it. --- ## 5. Selection 1. Rank all eligible candidates by the **total, data-driven ordering**: risk score descending, then vault age descending, then TVL descending, then ref_id ascending. Every tie-break is deterministic — a selection that could depend on map iteration order could not be reproduced, which would make the evidence chain worthless. 2. Take the top **10**. 3. **Incumbency buffer.** An incumbent constituent is displaced only if the challenger beats it by **0.2** of a risk score point **or** by **3** rank places. This suppresses churn from noise. The buffer is bypassed by extraordinary events (§12) — a hard-failed name leaves immediately. If fewer than 10 eligible names exist, the reconstitution is **infeasible** and reports why. PHIL10 does not publish a ten-name index with nine names, and does not lower a gate to reach the number. --- ## 6. Weighting **Equal weight**: each constituent's target is 1/N of the index, N = 10. The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75% safer than an 8.0, and score-weighting would make one estimate do two jobs, so a small scoring error would move both membership and capital. ### 6.1 Look-through caps Applied to the target weights by a deterministic cap-and-redistribution waterfall, on four dimensions: | Dimension | Cap | | --------- | ---- | | Protocol | 60% | | Issuer | 100% | | Curator | 35% | | Chain | 70% | Caps bind on the **look-through** dimension, not the vault name: two vaults on one protocol consume that protocol's cap jointly. Where a cap binds, weight is redistributed deterministically to uncapped names; the binding dimensions are recorded on the selection run. If the cap system cannot be satisfied, the reconstitution is infeasible and says so — caps are not quietly relaxed to force a result. **A null look-through key is membership in no group (v1.1.0).** A protocol-native vault (Aave, Spark, Compound, Yearn) has no curator: it belongs to no curator group and consumes no curator cap, in the trimming waterfall and in every verification of it alike. This is not a relaxation of the fail-closed rule — "there is no curator" is a measured fact about the vault's design, while "the curator is unknown where one should exist" is missing metadata, and missing metadata is an _eligibility_ exclusion decided before the waterfall ever runs (a curated-platform vault with no curator attribution is excluded as `curator_attribution_unavailable`). The same semantics apply to every cap dimension. **Cap levels are census-derived (v1.1.0).** The v1.0.0 levels (35/50/35/70) were set before any census had run against production. The first real census (2026-08-03, value date 2026-08-02) measured an eligible book that no 10-name equal-weight composition can satisfy under them: the measurable universe is Spark Savings and curated Morpho vaults in roughly equal number (each ~50% of a ten-name book against a 35% protocol cap), and 90–100% Circle-issued deposits (against a 50% issuer cap). A cap that admits no composition at all protects nothing. The v1.1.0 levels are the tightest caps the measured census satisfies with modest drift headroom: protocol 60%, issuer 100% (non-binding at glidepath start, stated plainly rather than pretended at), curator and chain unchanged. These remain a **glidepath**: they re-tighten as the eligible universe widens. Nothing re-tightens by itself — a 100% cap constrains nothing (weights always sum to exactly 100%, so the waterfall excludes such a dimension outright rather than letting rounding residue bind it) until a human lowers it, and like every cap change that takes a new methodology version with its own hash. Re-tightening the issuer cap is the first scheduled glidepath step once measurable non-Circle deposits exist, and each quarterly census is the standing occasion to take it. ### 6.2 Weight drift Between reconstitutions, weights **drift with performance**. They are not reset to target daily. Resetting daily would silently rebalance the index every day and publish a wrong level from day two onward — and both calculation engines would agree on it, because they would share the same malformed input. --- ## 7. Reconstitution ### 7.1 Schedule Scheduled reconstitutions are quarterly. A new composition is effective from a stated value date and governs closes **after** that date (§8.3). ### 7.2 Extraordinary reconstitution Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not apply. An index deletion is not a claim that a tracker could have exited at that price — see §16. ### 7.3 Evidence Every reconstitution records the full census: every candidate considered, every eligibility verdict with its reason, the ranking, the caps that bound, and the resulting composition — hashed and signed. ### 7.4 The bench The ranked eligible names that missed the cut are published with their rank. "Names 11–14 and exactly which rule keeps each one out" is part of the product, not a byproduct. --- ## 8. Calculation The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md` (fixed-point representation, rounding, primitive operations, bounds). It governs where it is more specific than this section. ### 8.1 Constituent return For constituent _i_ over the interval ending at value date _t_: ``` r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1 ``` `D` is distributions. The v1 universe is all-accruing, so **D = 0 by construction** — yield accrues inside NAV per share. A vault that distributes is ineligible (§4) precisely so this term cannot be silently wrong. FX is a real measured price, not an assumed $1.00. A depeg therefore flows into the index level mechanically, as a loss, rather than being invisible. ### 8.2 Index level ``` L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t) ``` Chain-linking is the definition, not an approximation. Opening weights are the previous close's **drifted** weights (§6.2), never the composition targets — except on the first close after a reconstitution took effect, which is what a reconstitution means. ### 8.3 Reconstitution boundary A composition effective for value date D applies from D's close **forward**. The return _ending_ at D is computed under the **outgoing** composition; the new targets open the next interval. Applying the incoming composition to D would compute D's return over a constituent set that was not in force during it. ### 8.4 Gaps If the previous accepted close is more than one day earlier, the interval is a **multi-day return**, correctly labelled as such — never a silently mislabelled one-day return. A multi-day interval may not span a reconstitution boundary: if it would, the close defers rather than applying weights retroactively to days they did not govern. ### 8.5 Precision Internal arithmetic is scaled integer at 8 decimal places with half-even rounding at defined points only. Published levels are stated at 2 decimal places. Value date, calculation timestamp and publication timestamp are distinct fields and are never conflated. --- ## 9. Data, provenance and verification ### 9.1 NAV `convertToAssets(1 share)` read on-chain at a **pinned block** per chain, after that chain's finality rule is satisfied. Before the read is accepted: `asset()` must still bind to the expected deposit asset; `totalSupply()` must be non-zero; the resulting NAV must be plausible; and a move beyond **500 bps** from the previous accepted NAV is **rejected**, not clamped — a clamped absurd input produces a plausible wrong number, the failure a benchmark can least afford. Share and asset decimals are **probed on-chain at registration** and persisted. They are never defaulted: a vault without probed conformance is not priced, the collection is therefore incomplete, and the close defers. ### 9.2 FX Push oracles only, from the families `chainlink`, `chronicle`, `redstone`, `api3`. The registry is keyed by **token address + chain**, never by symbol — symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark. The published FX is the **median of the responsive quorum**. A quote more than 200 bps from that median is **flagged and still counted** — it is not discarded. That is deliberate, and worth stating plainly because the intuitive rule is the opposite. Discarding a quote requires deciding it is wrong, and the median is already robust to a single bad source without that decision. More importantly, exclusion would make aggregation depend on a _prior pass's_ labels: replaying the stored evidence for a past close could then produce a different number from the one published, which would make the evidence package unverifiable. Flagging records the disagreement in the evidence without letting it change the arithmetic. Independence is counted by **oracle family**, and a single feed address may not be registered under more than one family — quorum is a claim about independent sources, not about rows. **A known dependency, stated because it is invisible otherwise.** Chronicle's mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller except a short allowlist, which includes the zero address. PHIL10 reads them as an off-chain indexer via `eth_call` with no `from`, which defaults to the zero address, so the reads succeed — but that permission is Chronicle's to revoke. If it were revoked, those quotes would begin erroring rather than returning a wrong number, the affected assets would fall from three responsive sources to two, and pricing would continue in a recorded degraded state. The failure mode is therefore visible and safe, but the dependency is real and is not something PHIL10 controls. Losing quorum does not produce a price: it produces a recorded degraded state with a reason. An asset with fewer than three independent feeds is a founder decision, not something the collector works around: such an asset is excluded from the universe by the FX-quorum gate (§4) rather than silently priced. ### 9.3 Collection coherence Every input row is stamped with a collection id. A completeness sentinel is written **last**, and only when every constituent produced both a NAV and a median. A crashed or partial collection leaves no sentinel and is never consumed — the close reads the last complete collection, or defers. ### 9.4 Dual-engine reconciliation Every close is computed twice: a primary scaled-integer engine in TypeScript and an independent engine in PostgreSQL `numeric`, over the **same sealed inputs** but on a different arithmetic substrate. Agreement is required at **zero tolerance** on the level, the daily return, each constituent return and each close weight. Disagreement **blocks publication**; it does not average, pick a side, or warn. ### 9.5 Evidence Every close emits a signed evidence package: the sealed inputs, both engines' results, the reconciliation, the governing composition and methodology version, engine versions and hashes. Signatures are Ed25519; the public half of every signing key is registered in an append-only registry before use, so historical signatures remain verifiable across key rotation. ### 9.6 Append-only Observations, inputs, runs and evidence are **insert-only**, enforced by database triggers, including protection against TRUNCATE. A correction is a new revision plus a notice (§13). History is never edited. --- ## 10. Staleness ladder and statuses | Input age at close | Effect | | ------------------ | --------------------------------------------------------- | | ≤ 6h | Normal | | > 6h | Constituent flagged; close proceeds | | > 48h | Close proceeds, status records calculation on stale input | | > 72h | **Close is `not_calculated`** | A single constituent past 72h makes the whole close `not_calculated`. Constituents are **never dropped and renormalized to rescue a close** — that would silently change the composition on precisely the days the data is worst. A carried-forward annualized rate is never accrued. **Status vocabulary** (fixed; these exact words appear in the API): `preliminary`, `official`, `revised`, `delayed`, `insufficient_data`, `not_calculated`, `back_calculated`. An honest gap is **permanent**: once a later close has been accepted, a skipped date is not retroactively filled, because doing so would break the internal chaining of an already-signed series. --- ## 11. Publication Closes are calculated after the value date's close instant and after chain finality. The target publication time is 16:30 UTC. A late close is published late and labelled, never backdated. A close that cannot be computed is recorded with the reason — silence is not a permitted outcome, and a dead-man's watchdog alerts if a value date passes with no observation. --- ## 12. Depeg ladder Evaluated on the deposit asset against a two-source-minimum quorum: | Condition | Action | | --------------------------- | -------------------------------------------- | | < $0.985 for 4 hours | Review flagged | | < $0.97 for 15 minutes | Extraordinary review flagged | | < $0.95, quorum-confirmed | **Presumptive removal** | | < $0.95, single source only | Extraordinary flagged (removal needs quorum) | Flags annotate a close; they never block it. Severity is **monotonic within an open episode** — it can only rise. It clears only through the quorum-guarded recovery exit that closes the episode; a single low-confidence tick can never downgrade a confirmed removal and re-admit a still-depegged vault. A depeg is also visible in the level itself, because FX is measured (§8.1). --- ## 13. Corrections and restatement An error is corrected by **new revisions plus a numbered public notice** stating what changed, why, which value dates are affected and what the levels were before and after. Prior revisions remain queryable forever. The methodology version and composition that governed each revision remain attached to it. --- ## 14. Governance - **Index committee:** two founders. The external seat is deliberately **open** (see §0) and will be filled when the right person is found rather than for appearance. - **Methodology changes** are new versions with new hashes. Non-emergency changes carry a public consultation period once the index is public. - **Conflicts:** Philidor operates no product tracking PHIL10, and none is planned for v1. Risk-assessment commercial relationships with constituents' operators, where they exist, are disclosed as a category. The controlling rule, which admits no exception: **money can buy coverage, custom products and calculation services; it can never buy a risk score or a seat in a standard index.** - **Cessation:** if PHIL10 stops being calculated, that is announced with a notice and the historical series remains published and verifiable. --- ## 15. Regulatory status PHIL10 is private and unpublished, licensed to no one, and tracked by no product. No regulatory-status claim is made in this version. A counsel-reviewed benchmark statement is a prerequisite for public inception, not for this document. Nothing here is investment advice. --- ## 16. Known limitations Stated exactly, because a rulebook that hides them is not worth publishing: 1. **The universe is small and concentrated.** Ten names drawn from a single-digit-to-low-double-digit eligible set, historically dominated by one or two protocols. Caps (§6.1) are set at glidepath levels for exactly this reason, and the binding dimensions are published per reconstitution. 2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is measured; the horizon is not observable on-chain. 3. **Index deletion is not tracker realizability.** An extraordinary reconstitution removes a name from the index; it does not assert that a holder could have exited at that price, or at all. 4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic loss looks implausible, so the close defers rather than recording it. This is deliberate fail-closed behaviour and an open founder decision: a crisis confirmation path is required before PHIL10 can claim to measure a crisis. 5. **No external methodology review** (§0). 6. **No public track record.** The series is preliminary and the soak is private. Elapsed operating time cannot be simulated or shortened. 7. **No back-calculated history is published in v1.** Point-in-time score history is not reconstructable far enough back to do it honestly. --- ## 17. Version history | Version | Date | Change | | ------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. | | 1.1.0 | 2026-08-03 | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key = no group, with curated-platform attribution failures excluded at eligibility; mechanism-attestation evidence path for the all-accruing gate (Spark). | | Census-derived cap reset (protocol 60%, issuer 100%); null look-through key means no group; mechanism-attestation evidence path for the all-accruing gate. |
| 1.0.0 | 2026-07-24 | PHIL10 — Index Methodology sha256 f6c4235cbbd2666bcfc710d04513589f813d2301cb0d0c6ec45ae392db7dcd11 Read the document (24 KB)# PHIL10 — Index Methodology **Index:** The Philidor Onchain Dollar Yield Index 10 **Code:** `PHIL10` · **Return variant:** `PHIL10-TR` (total return) · **Currency:** USD **Methodology version:** 1.0.0 **Administrator:** Philidor Labs --- ## 0. Status of this document and of the index **PHIL10 is not an official benchmark and has no official inception date.** This document governs a **private operational soak**: the engine calculates a daily level from real on-chain data, on a real schedule, under real fail-closed rules, and every observation it produces carries the status `preliminary`. Nothing is published publicly, no product may track it, and the level series is not a track record. Two things follow, and they are stated here because a rulebook that overclaims is worse than none: 1. **Official inception is a separate, later act.** It requires a base date, a base value of 100.00, a public preliminary period, and the governance apparatus in §14 actually operating. Until then the series is a systems artefact, not a benchmark. 2. **No external methodology review has been performed.** The founders decided on 2026-07-22 to hold the external reviewer seat open until the right person is found rather than fill it for form's sake. Until that review exists, the compensating controls are: this document published in full, the dual-engine reconciliation of §9.4, the signed evidence of §9.5, and the honest limitations of §16. This document is versioned and content-hashed. The hash of the exact bytes of this file is recorded in `index_methodology_versions.content_hash`, and every composition and observation references the methodology version under which it was produced. --- ## 1. Objective PHIL10 is a rules-based, total-return index designed to measure a diversified set of risk-qualified, implementation-eligible USD-denominated onchain yield strategies. It answers one question: _what does a disciplined dollar allocator actually earn across the onchain venues that pass a real risk screen and can genuinely be entered and exited?_ It is deliberately **not** a market-coverage index. Breadth is not the goal; qualification is. Names 11 and beyond are excluded on purpose, and the published bench (§7.4) states exactly which rule excluded each one. --- ## 2. Definitions | Term | Meaning in this document | | ------------------ | ----------------------------------------------------------------------------------------------------- | | **Value date (D)** | The calendar date a close belongs to. Closes at exactly **D 16:00:00.000 UTC**. | | **Close** | The daily calculation producing one official level for one value date. | | **Constituent** | A vault included in the composition governing a value date. | | **Composition** | The constituent set and target weights established by a reconstitution, effective from a stated date. | | **Reconstitution** | The act of establishing a new composition (scheduled or extraordinary). | | **NAV per share** | `convertToAssets(1 share)` read on-chain at the pinned close block. | | **FX** | The USD price of a constituent's deposit asset, from a push-oracle quorum. | | **Observation** | One published (index, value date, revision) row with a level and a status. | | **Collection** | One complete run of the input collector, identified by a collection id. | --- ## 3. Universe A tracked vault is in the candidate universe if **all** of the following hold. Every exclusion carries a machine-readable reason, so the census can state why a name is out without a human re-deriving it. 1. **Deposit asset is an eligible onchain dollar:** `USDC`, `USDT`, or `USDT0`. 2. **Single-asset exposure.** A vault whose asset components list more than one asset (e.g. USDC/WETH) is excluded — it is not a dollar vault. 3. **Active and not shut down.** 4. **Chain is not held out.** Held-out chain ids are enumerated in code and currently comprise chain `9745`. 5. **The asset address is known.** Identity is (address, chain) everywhere downstream — FX feeds, adapters, caps. A candidate without an asset address cannot be carried honestly, so it is excluded rather than symbol-matched. **Synthetic, algorithmic and yield-bearing dollars are excluded by name**, not merely by canonicalization: USDe, sUSDe, crvUSD, GHO, DAI, sDAI, USDS, sUSDS, FRAX, sFRAX, LUSD, MIM, USD0, USDX, deUSD, RLUSD, PYUSD, FDUSD, USDY and others enumerated in code. The list exists so the exclusion is reviewable, and so a new synthetic that slips past canonicalization is still caught by name. **Issuer aggregation:** USDT and USDT0 share the issuer `tether`; USDC maps to `circle`. USDT0 is a wrapper with its own bridge and messaging dependencies, and is treated as a distinct asset that nonetheless consumes the Tether issuer cap. --- ## 4. Eligibility A universe member must additionally pass **every** gate below. Order affects only which reason is reported first. | Gate | Threshold | | ------------------------- | ---------------------------------------------------------------------------- | | Risk vectors readable | Required — see fail-closed rule | | Hard-fail flag | Must be absent | | Depeg presumptive removal | Must be absent | | Incident clamp | Must be absent | | All-accruing | Required (v1 universe pays no distributions) | | Reviewed | Required | | Philidor risk score | ≥ **8.0** (Prime) | | Vault TVL | ≥ **$5,000,000** | | Vault age | ≥ **90 days** | | Liquidity tier 1 | $1,000,000 redeemable within 24h at ≤ **10 bps** | | Liquidity tier 2 | $5,000,000 redeemable within 7d at ≤ **50 bps** | | Stressed clip | ≤ **20%** of vault TVL | | FX feed quorum | ≥ **3 independent** push-oracle families for the deposit asset on that chain | The FX-quorum gate is the pricing counterpart of the fail-closed rule below: a vault whose deposit asset cannot reach a price quorum on its chain is not priced conservatively, it cannot be priced **at all**, and including it would stop the index rather than degrade it. Independence is counted by oracle _family_, not by contract: two feeds from the same provider are one source. ### 4.1 The fail-closed rule **"We could not measure it" and "it passed" must never produce the same outcome.** A candidate whose liquidity test could not be executed, or whose risk vectors could not be read, is **ineligible** — it is never waved through. These are reported as distinct reasons (`liquidity_test_unavailable`, `risk_vectors_unavailable`) so the census can tell an unmeasurable name apart from an illiquid one. ### 4.2 What the liquidity test measures, and what it assumes Stated plainly because the boundary is real: - **Measured:** exit cost, against the fee-free `convertToAssets` rate, at both clip sizes, read on-chain at a pinned block. - **Measured:** instantaneous capacity for tier 1, via `maxWithdraw`, which folds in the vault's currently available liquidity. - **Assumed:** the 7-day horizon. No ERC-4626 read reveals how quickly an underlying position unwinds, so tier-2 capacity is evaluated against total assets, which **assumes an orderly 7-day unwind**. The assumption is recorded in the signed evidence for every candidate so a reader sees it rather than infers it. This is a known limitation, restated in §16, and a live founder decision: either accept the orderly-unwind assumption or require real unwind evidence and exclude names that cannot supply it. --- ## 5. Selection 1. Rank all eligible candidates by the **total, data-driven ordering**: risk score descending, then vault age descending, then TVL descending, then ref_id ascending. Every tie-break is deterministic — a selection that could depend on map iteration order could not be reproduced, which would make the evidence chain worthless. 2. Take the top **10**. 3. **Incumbency buffer.** An incumbent constituent is displaced only if the challenger beats it by **0.2** of a risk score point **or** by **3** rank places. This suppresses churn from noise. The buffer is bypassed by extraordinary events (§12) — a hard-failed name leaves immediately. If fewer than 10 eligible names exist, the reconstitution is **infeasible** and reports why. PHIL10 does not publish a ten-name index with nine names, and does not lower a gate to reach the number. --- ## 6. Weighting **Equal weight**: each constituent's target is 1/N of the index, N = 10. The risk score _selects_; it does not _size_. An 8.7 is not demonstrably 8.75% safer than an 8.0, and score-weighting would make one estimate do two jobs, so a small scoring error would move both membership and capital. ### 6.1 Look-through caps Applied to the target weights by a deterministic cap-and-redistribution waterfall, on four dimensions: | Dimension | Cap | | --------- | --- | | Protocol | 35% | | Issuer | 50% | | Curator | 35% | | Chain | 70% | Caps bind on the **look-through** dimension, not the vault name: two vaults on one protocol consume that protocol's cap jointly. Where a cap binds, weight is redistributed deterministically to uncapped names; the binding dimensions are recorded on the selection run. If the cap system cannot be satisfied, the reconstitution is infeasible and says so — caps are not quietly relaxed to force a result. These levels are a **glidepath start**, appropriate to a universe this concentrated. They tighten as the eligible universe widens; any change is a methodology version with its own hash. ### 6.2 Weight drift Between reconstitutions, weights **drift with performance**. They are not reset to target daily. Resetting daily would silently rebalance the index every day and publish a wrong level from day two onward — and both calculation engines would agree on it, because they would share the same malformed input. --- ## 7. Reconstitution ### 7.1 Schedule Scheduled reconstitutions are quarterly. A new composition is effective from a stated value date and governs closes **after** that date (§8.3). ### 7.2 Extraordinary reconstitution Triggered outside the schedule by: a hard-fail flag, an incident clamp, loss of Prime tier, or a depeg presumptive removal (§12). The incumbency buffer does not apply. An index deletion is not a claim that a tracker could have exited at that price — see §16. ### 7.3 Evidence Every reconstitution records the full census: every candidate considered, every eligibility verdict with its reason, the ranking, the caps that bound, and the resulting composition — hashed and signed. ### 7.4 The bench The ranked eligible names that missed the cut are published with their rank. "Names 11–14 and exactly which rule keeps each one out" is part of the product, not a byproduct. --- ## 8. Calculation The normative arithmetic contract is `packages/shared/src/indices/ARITHMETIC.md` (fixed-point representation, rounding, primitive operations, bounds). It governs where it is more specific than this section. ### 8.1 Constituent return For constituent _i_ over the interval ending at value date _t_: ``` r_i,t = (NAV_i,t × FX_i,t + D_i,t) / (NAV_i,t-1 × FX_i,t-1) − 1 ``` `D` is distributions. The v1 universe is all-accruing, so **D = 0 by construction** — yield accrues inside NAV per share. A vault that distributes is ineligible (§4) precisely so this term cannot be silently wrong. FX is a real measured price, not an assumed $1.00. A depeg therefore flows into the index level mechanically, as a loss, rather than being invisible. ### 8.2 Index level ``` L_t = L_t-1 × (1 + Σ_i w_i,t-1 × r_i,t) ``` Chain-linking is the definition, not an approximation. Opening weights are the previous close's **drifted** weights (§6.2), never the composition targets — except on the first close after a reconstitution took effect, which is what a reconstitution means. ### 8.3 Reconstitution boundary A composition effective for value date D applies from D's close **forward**. The return _ending_ at D is computed under the **outgoing** composition; the new targets open the next interval. Applying the incoming composition to D would compute D's return over a constituent set that was not in force during it. ### 8.4 Gaps If the previous accepted close is more than one day earlier, the interval is a **multi-day return**, correctly labelled as such — never a silently mislabelled one-day return. A multi-day interval may not span a reconstitution boundary: if it would, the close defers rather than applying weights retroactively to days they did not govern. ### 8.5 Precision Internal arithmetic is scaled integer at 8 decimal places with half-even rounding at defined points only. Published levels are stated at 2 decimal places. Value date, calculation timestamp and publication timestamp are distinct fields and are never conflated. --- ## 9. Data, provenance and verification ### 9.1 NAV `convertToAssets(1 share)` read on-chain at a **pinned block** per chain, after that chain's finality rule is satisfied. Before the read is accepted: `asset()` must still bind to the expected deposit asset; `totalSupply()` must be non-zero; the resulting NAV must be plausible; and a move beyond **500 bps** from the previous accepted NAV is **rejected**, not clamped — a clamped absurd input produces a plausible wrong number, the failure a benchmark can least afford. Share and asset decimals are **probed on-chain at registration** and persisted. They are never defaulted: a vault without probed conformance is not priced, the collection is therefore incomplete, and the close defers. ### 9.2 FX Push oracles only, from the families `chainlink`, `chronicle`, `redstone`, `api3`. The registry is keyed by **token address + chain**, never by symbol — symbol-keyed pricing is how a "USDT0 is $1" shortcut leaks into a benchmark. The published FX is the **median of the responsive quorum**. A quote more than 200 bps from that median is **flagged and still counted** — it is not discarded. That is deliberate, and worth stating plainly because the intuitive rule is the opposite. Discarding a quote requires deciding it is wrong, and the median is already robust to a single bad source without that decision. More importantly, exclusion would make aggregation depend on a _prior pass's_ labels: replaying the stored evidence for a past close could then produce a different number from the one published, which would make the evidence package unverifiable. Flagging records the disagreement in the evidence without letting it change the arithmetic. Independence is counted by **oracle family**, and a single feed address may not be registered under more than one family — quorum is a claim about independent sources, not about rows. **A known dependency, stated because it is invisible otherwise.** Chronicle's mainnet oracles are _toll-gated_: a read reverts `NotTolled` for every caller except a short allowlist, which includes the zero address. PHIL10 reads them as an off-chain indexer via `eth_call` with no `from`, which defaults to the zero address, so the reads succeed — but that permission is Chronicle's to revoke. If it were revoked, those quotes would begin erroring rather than returning a wrong number, the affected assets would fall from three responsive sources to two, and pricing would continue in a recorded degraded state. The failure mode is therefore visible and safe, but the dependency is real and is not something PHIL10 controls. Losing quorum does not produce a price: it produces a recorded degraded state with a reason. An asset with fewer than three independent feeds is a founder decision, not something the collector works around: such an asset is excluded from the universe by the FX-quorum gate (§4) rather than silently priced. ### 9.3 Collection coherence Every input row is stamped with a collection id. A completeness sentinel is written **last**, and only when every constituent produced both a NAV and a median. A crashed or partial collection leaves no sentinel and is never consumed — the close reads the last complete collection, or defers. ### 9.4 Dual-engine reconciliation Every close is computed twice: a primary scaled-integer engine in TypeScript and an independent engine in PostgreSQL `numeric`, over the **same sealed inputs** but on a different arithmetic substrate. Agreement is required at **zero tolerance** on the level, the daily return, each constituent return and each close weight. Disagreement **blocks publication**; it does not average, pick a side, or warn. ### 9.5 Evidence Every close emits a signed evidence package: the sealed inputs, both engines' results, the reconciliation, the governing composition and methodology version, engine versions and hashes. Signatures are Ed25519; the public half of every signing key is registered in an append-only registry before use, so historical signatures remain verifiable across key rotation. ### 9.6 Append-only Observations, inputs, runs and evidence are **insert-only**, enforced by database triggers, including protection against TRUNCATE. A correction is a new revision plus a notice (§13). History is never edited. --- ## 10. Staleness ladder and statuses | Input age at close | Effect | | ------------------ | --------------------------------------------------------- | | ≤ 6h | Normal | | > 6h | Constituent flagged; close proceeds | | > 48h | Close proceeds, status records calculation on stale input | | > 72h | **Close is `not_calculated`** | A single constituent past 72h makes the whole close `not_calculated`. Constituents are **never dropped and renormalized to rescue a close** — that would silently change the composition on precisely the days the data is worst. A carried-forward annualized rate is never accrued. **Status vocabulary** (fixed; these exact words appear in the API): `preliminary`, `official`, `revised`, `delayed`, `insufficient_data`, `not_calculated`, `back_calculated`. An honest gap is **permanent**: once a later close has been accepted, a skipped date is not retroactively filled, because doing so would break the internal chaining of an already-signed series. --- ## 11. Publication Closes are calculated after the value date's close instant and after chain finality. The target publication time is 16:30 UTC. A late close is published late and labelled, never backdated. A close that cannot be computed is recorded with the reason — silence is not a permitted outcome, and a dead-man's watchdog alerts if a value date passes with no observation. --- ## 12. Depeg ladder Evaluated on the deposit asset against a two-source-minimum quorum: | Condition | Action | | --------------------------- | -------------------------------------------- | | < $0.985 for 4 hours | Review flagged | | < $0.97 for 15 minutes | Extraordinary review flagged | | < $0.95, quorum-confirmed | **Presumptive removal** | | < $0.95, single source only | Extraordinary flagged (removal needs quorum) | Flags annotate a close; they never block it. Severity is **monotonic within an open episode** — it can only rise. It clears only through the quorum-guarded recovery exit that closes the episode; a single low-confidence tick can never downgrade a confirmed removal and re-admit a still-depegged vault. A depeg is also visible in the level itself, because FX is measured (§8.1). --- ## 13. Corrections and restatement An error is corrected by **new revisions plus a numbered public notice** stating what changed, why, which value dates are affected and what the levels were before and after. Prior revisions remain queryable forever. The methodology version and composition that governed each revision remain attached to it. --- ## 14. Governance - **Index committee:** two founders. The external seat is deliberately **open** (see §0) and will be filled when the right person is found rather than for appearance. - **Methodology changes** are new versions with new hashes. Non-emergency changes carry a public consultation period once the index is public. - **Conflicts:** Philidor operates no product tracking PHIL10, and none is planned for v1. Risk-assessment commercial relationships with constituents' operators, where they exist, are disclosed as a category. The controlling rule, which admits no exception: **money can buy coverage, custom products and calculation services; it can never buy a risk score or a seat in a standard index.** - **Cessation:** if PHIL10 stops being calculated, that is announced with a notice and the historical series remains published and verifiable. --- ## 15. Regulatory status PHIL10 is private and unpublished, licensed to no one, and tracked by no product. No regulatory-status claim is made in this version. A counsel-reviewed benchmark statement is a prerequisite for public inception, not for this document. Nothing here is investment advice. --- ## 16. Known limitations Stated exactly, because a rulebook that hides them is not worth publishing: 1. **The universe is small and concentrated.** Ten names drawn from a single-digit-to-low-double-digit eligible set, historically dominated by one or two protocols. Caps (§6.1) are set at glidepath levels for exactly this reason, and the binding dimensions are published per reconstitution. 2. **Tier-2 liquidity assumes an orderly 7-day unwind** (§4.2). The cost leg is measured; the horizon is not observable on-chain. 3. **Index deletion is not tracker realizability.** An extraordinary reconstitution removes a name from the index; it does not assert that a holder could have exited at that price, or at all. 4. **A catastrophic single-day loss can freeze rather than record.** The 500 bps NAV anomaly bound (§9.1) rejects implausible moves. A genuine catastrophic loss looks implausible, so the close defers rather than recording it. This is deliberate fail-closed behaviour and an open founder decision: a crisis confirmation path is required before PHIL10 can claim to measure a crisis. 5. **No external methodology review** (§0). 6. **No public track record.** The series is preliminary and the soak is private. Elapsed operating time cannot be simulated or shortened. 7. **No back-calculated history is published in v1.** Point-in-time score history is not reconstructable far enough back to do it honestly. --- ## 17. Version history | Version | Date | Change | | ------- | ---------- | ----------------------------------------------------------- | | 1.0.0 | 2026-07-24 | Initial methodology governing the private operational soak. | | Initial methodology governing the private operational soak. |
Static catalogue transcribed from the documents’ own version history; hashes are SHA-256 over the exact document bytes. The registry is authoritative — the live panel above shows what it reports for the current version, so any drift is visible. The full registered history will render live here once the methodology endpoint ships.
Verifying a document
Compute sha256(document bytes)over the exact file — not a summary, not a rendering — and compare it to the registered hash. A version whose hash was computed over “the summary someone pasted” is a version that cannot be audited; that is why the registry refuses to re-register a changed document under an existing version string.