Skip to content

fix(ingest): classify v3/yearn vaults consistently across discovery paths - #458

Open
matheus1lva wants to merge 2 commits into
mainfrom
fix/v3-yearn-vault-classification
Open

fix(ingest): classify v3/yearn vaults consistently across discovery paths#458
matheus1lva wants to merge 2 commits into
mainfrom
fix/v3-yearn-vault-classification

Conversation

@matheus1lva

@matheus1lva matheus1lva commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Mainnet Ondo Aggregator 0xACA399117aC588E1F48398d34eCA76CDB1E45fA5 (apiVersion 3.0.2) serves
v3: false on the REST vault list and v3: null on GraphQL because v3/yearn only exist in
thing.defaults and several discovery paths never write them. This adds one shared
classifyVault(apiVersion) helper ({ yearn, v3: apiVersion >= 3.0.0, apiVersion }), applies it in the
StrategyChanged else-branch, adds yearn: true in the vaultFactory/roleManager hooks so those vaults stop
dual-matching the generic erc4626 convention, and adds the missing v3: true flags in config/manuals.yaml.

How to review

Start with packages/ingest/helpers/classify-vault.ts: version compare reuses compare from
compare-versions + clean from lib/version, the same pair as packages/ingest/things.ts. The helper
takes an optional string and returns undefined for falsy or non-semver input, so a contract returning
apiVersion() = "yVault" falls back to the unresolved path instead of throwing. It returns the cleaned
version, not the raw one — clean() strips non-semver characters, so a raw 3.0.2rc would pass
validate() and then make the compare() calls in abis/yearn/lib/tvl.ts and abis/yearn/lib/apy.ts
throw on read.

Then StrategyChanged/hook.ts: the else-branch merges helper output only when the classification resolves
to v3. Anything reaching that branch is 4626-shaped, so a sub-3.0.0 classification is never the right
outcome — writing apiVersion alone would match the yearn/2/vault convention (whose hooks expect
token()/pricePerShare), and yearn: true alone would evict the thing from the erc4626 convention.
The tokenized branch adds yearn: true to the vault-labeled record only, and the three mq.add calls are
now awaited. The manuals.yaml edits are 8 chain-100 entries that had apiVersion without v3.

Test plan

  • Manual: after deploy, replay discovery events, drain queues, run a fresh ABI fanout, refresh the
    REST vault cache, then check Ondo on REST list / GraphQL / REST snapshot for v3: true.
  • Automated: bunx vitest run helpers/classify-vault.spec.ts abis/yearn/3/vault/event/StrategyChanged/hook.spec.ts
    from packages/ingest — 12/12 pass (helper version edges incl. the 3.0.0 boundary, cleaned-output cases
    v3.0.2 / 0.4.6-beta / 3.0.2rc, garbage and empty input; hook resolved/sub-3.0.0/unresolved/garbage/
    tokenized cases).

Risk / impact

yearn: true flips backfilled vaults from the erc4626 convention to yearn/3 hooks and adds them to
GraphQL yearn: true / origin-yearn filters and the timeseries resolver (accepted in the plan). Stale
erc4626 hook keys in snapshots are already shadowed by contract state on read. Non-yearn contracts that
expose an apiVersion() of 3.0.0 or above get classified as yearn (accepted); below 3.0.0 they keep their
erc4626 classification unchanged. Rollback: revert, replay, re-fanout.

Known gaps

  • The vaultFactory and roleManager yearn: true edits have no test, and output/timeseries rows already
    written under erc4626 hook keys for backfilled vaults are not graded — only snapshots are.
  • classifyVault has one call site. vaultFactory, roleManager and the three v3 registry hooks still stamp
    v3: true regardless of the apiVersion they read.
  • config/manuals.yaml:37 and :52 keep yearn: false alongside apiVersion: '3.0.1', so they still
    dual-match erc4626 and yearn/3.

@vercel

vercel Bot commented Aug 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
kong Ready Ready Preview Aug 20, 2026 1:48pm

Request Review

Gate the StrategyChanged else-branch merge on the classification resolving
to v3. A sub-3.0.0 apiVersion previously wrote yearn/v3/apiVersion into the
defaults, which evicted the thing from the erc4626 convention and routed it
to yearn/2/vault, whose hooks expect token()/pricePerShare, not a 4626
surface.

classifyVault now returns the cleaned version instead of the raw one. clean()
strips non-semver characters, so '3.0.2rc' passed validate() while the raw
string was persisted and made downstream compare() calls in tvl.ts and apy.ts
throw. It also takes an optional argument and returns undefined on falsy
input, so clean()'s throw is no longer reachable through it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant