Skip to content

Add yTranche indexing and REST support #444

Description

@murderteeth

Description

Add support for the current Ethereum yTranche deployment. Kong will discover tranches through the controller, retain controller state, enrich tranche snapshots with current Hook state, generate controller-backed tranche PPS and performance history, and expose the data through REST only.

Scope

Deployment:

Component Address
Main vault 0xDa87123895a043Ed3610155550177C54ce8ba49B
Controller 0xF0145433E5289dd10712650dCd28333FA317eF36
Hook 0x776DEd3273440f1481d07B6CE916b5d5Fac170dC

A controller is bound to one asset class: ASSET and VAULT are constructor arguments with no setters, so a USD, BTC and ETH system each require their own controller. Only the USD deployment above is indexed, and nothing may assume a chain has exactly one controller.

Out of scope:

  • GraphQL changes
  • Shareholder balances or cooldown state
  • Indexing additional deployments or chains — though everything keyed by controller must admit more than one per chain
  • Hook things or standalone Hook snapshots
  • Hook-change tracking
  • New event hooks
  • New REST performance shapes
  • Governance and transaction execution

Internal naming

Use functional names without the y prefix:

  • trancheController
  • tranche

Use “yTranche” in documentation and user-facing descriptions.

Tasks

1. Index the deployment

Add controller and tranche ABIs as sibling paths:

packages/ingest/abis/yearn/3/tranche/controller/
packages/ingest/abis/yearn/3/tranche/vault/
packages/ingest/abis/yearn/3/tranche/hook/

They must be siblings rather than sharing a yearn/3/tranche hook path: kong's hook resolver applies a parent path's hooks to every child path, which would cross-wire the controller and the tranches.

Include the Hook read interface required by the tranche snapshot hook. Configure the Ethereum controller as a static source in config/abis.yaml.

Events contained in the configured ABIs must be indexed through Kong’s existing automatic event extraction. Do not add event hooks.

2. Discover tranches

Add a controller snapshot hook that:

  • Reads VAULT, ASSET, reserveVault, tranchesLength, and tranchesByPriority.
  • Discovers every registered tranche in priority order.
  • Creates or updates the required tranche, vault, and strategy things.
  • Creates or updates a trancheController thing carrying asset, mainVault, inceptBlock and inceptTime, whether or not any tranches are registered. Deployments are enumerated from this label rather than from the tranches pointing at it.
  • Adds these defaults to each tranche:
trancheController
priority
trancheType
asset
mainVault
inceptBlock
inceptTime
erc4626
v3
yearn

trancheType identifies whether the contract uses the base or locked tranche implementation. A/B/E names are not used as protocol types.

The indexing configuration must ensure each tranche address has one snapshot owner and is not independently processed by conflicting generic ABI paths.

3. Enrich the controller snapshot with tranche state

Kong’s automatic controller snapshot stores the controller’s zero-argument state.

The controller snapshot hook must use tranchesLength and tranchesByPriority(index) to append an ordered tranches array. For each tranche, read tranches(tranche), liveAssets(tranche), and trancheCoverage(tranche).

Each tranche entry must contain:

address
priority
registered
accrualPaused
excessShareBps
targetRatePerSecondWad
baselineAssets
lastAccrual
pendingExcess
liveAssets
claim
covered

Use the automatic snapshot’s block for every appended read.

4. Enrich tranche snapshots with Hook state

Kong’s automatic tranche snapshot stores the current Solidity hook() return value as the raw hook address.

The tranche snapshot hook must use that address to append a separate hookState object containing:

open
rateLimitWindow
depositLimit
depositRateLimit.used
depositRateLimit.windowStart
depositRateLimit.rateLimit
withdrawRateLimit.used
withdrawRateLimit.windowStart
withdrawRateLimit.rateLimit
depositCap
withdrawCap

Requirements:

  • Read parameterized Hook properties using the tranche address as the target.
  • depositLimit is the Hook's depositLimits(tranche) value.
  • Preserve hook as the raw Hook address.
  • Store derived Hook properties under hookState; do not return a second top-level hook field from the snapshot hook.
  • Use the same block as the tranche snapshot.
  • Store fixed-window counters as reported.
  • The REST response may additionally expose effective usage after applying the snapshot timestamp and rateLimitWindow.
  • Do not create a Hook thing.
  • Do not store a standalone Hook snapshot.
  • Do not index account-specific allowed or cooldown mappings.

5. Add accounting time series

Generate one daily tranche-accounting series per tranche:

baselineAssets
pendingExcess
liveAssets
claim
covered
coverageRatio
targetRatePerSecondWad
excessShareBps
accrualPaused

Generate one daily tranche-system series at the controller address:

totalClaims
vaultAssets
reserveAssets
backingAssets
coverageRatio

Values must be read at a single historical block for each observation. coverageRatio is null when there is no claim to cover — no claim is not evidence of full coverage.

6. Support controller-backed assets, PPS, and TVL-C

Refactor the existing vault calculations to obtain the authoritative asset balance through a shared function that accepts a vault thing and block number.

For ordinary vaults, read:

vault.totalAssets()

When the vault thing has a trancheController default, read:

trancheController.liveAssets(vault)

Use the authoritative asset balance in the existing tvl-c calculation.

For ordinary vault PPS, continue reading:

vault.pricePerShare()

For tranche PPS, calculate:

authoritativeAssets × 10^vaultDecimals / vault.totalSupply()

When totalSupply is zero, return 10^vaultDecimals.

Use the resulting PPS reader for every current, weekly, monthly, and inception observation required by:

pps
apy-bwd-delta-pps

trancheController.liveAssets(vault) already excludes pendingExcess; do not add pending excess to PPS or TVL.

Keep the existing output labels, components, pricing, historical sampling, annualization, compounding, storage, and REST shapes unchanged. Existing non-tranche vault calculations must remain unchanged.

7. Add REST resources

Add a collection and a member endpoint:

GET /api/rest/tranche/:chainId/controllers
GET /api/rest/tranche/:chainId/:controller

The collection returns every system on the chain, one document per controller. The member returns one, addressed by controller. controllers is a static route segment, so it resolves ahead of the member route.

Each document returns:

controller
asset
mainVault
reserveVault
system accounting
ordered tranches
blockNumber
blockTime

Each tranche entry must include its thing metadata, current hook address, hookState, controller accounting, current PPS, coverage, and effective deposit and withdrawal capacity.

Expose the new historical labels through Kong’s existing timeseries REST mechanism:

tranche-accounting
tranche-system
pps
apy-historical

Do not add GraphQL fields or resolvers.

8. Prevent double counting

Tranche TVL represents claims on the main vault’s backing, not additional protocol assets.

  • Emit tranche tvl-c outputs using trancheController.liveAssets(tranche).
  • Do not emit the legacy tvl label for tranche vaults.
  • Do not create or calculate an aggregate that sums main-vault TVL and tranche TVL as independent backing.
  • Do not include pendingExcess in live tranche NAV or TVL.
  • Keep accounting coverage separate from immediately deliverable withdrawal capacity.

9. Tests and documentation

Add focused tests using Kong’s existing unit and fixed-block RPC test patterns:

  • Verify authoritative asset source selection: ordinary vaults use totalAssets() and vault things with trancheController use liveAssets(vault).
  • Verify controller-backed assets against the deployed controller at a fixed block.
  • Verify tranche PPS against authoritativeAssets × scale / totalSupply at a fixed block.
  • Verify zero-supply PPS returns the share scale when the calculation is implemented as a pure helper.
  • Verify ordinary vault PPS continues using pricePerShare().
  • Verify APY obtains its current, weekly, monthly, and inception PPS observations through the shared PPS reader.
  • Verify tvl-c consumes the authoritative asset balance while preserving its existing output shape.
  • Verify tranche vaults do not emit the legacy tvl label.
  • Verify controller discovery returns the deployed tranche addresses in priority order at a fixed block.
  • Verify tranche snapshot enrichment preserves the raw hook address and appends representative limit data under hookState.

Do not add new testing infrastructure or broad container-level tests for this work.

Document the REST endpoint, timeseries labels, accounting semantics, snapshot naming distinction, and current deployment.

Reference: yTranche contracts

Acceptance criteria

  • Kong discovers all current tranches from the controller without hardcoded tranche addresses.
  • The controller snapshot is retained with block metadata.
  • The controller has a trancheController thing, and REST enumerates deployments from it.
  • Each tranche has trancheController, priority, and type metadata.
  • Each tranche snapshot retains the raw hook address and enriched hookState.
  • No Hook thing or standalone Hook snapshot is created.
  • Controller accounting and backing series are generated daily.
  • Tranche PPS and historical APY use controller-backed PPS.
  • Tranche tvl-c uses controller-backed assets and does not emit legacy tvl.
  • Existing PPS, APY, and REST output shapes remain unchanged.
  • yTranche data is available through REST without GraphQL changes.
  • Events are indexed without event hooks.
  • Shareholder cooldown state is not indexed.
  • Tranche claims are not counted as additional protocol TVL.
  • Existing non-tranche vault behavior remains unchanged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions