Resolve vault allocators from Kong assignment logs - #472
Conversation
Materialize current allocator assignments independently of deployment provenance. Serve both GraphQL paths and snapshot ratios from the same saved revision, preserving arbitrary addresses and explicit unavailable configuration.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Keep the last validated allocator block outside the replaceable projection so failures cannot allow older assignments to reappear. Cover failed reads, lagging recovery, same-block recovery, explicit clears, and zero ratios, including both Postgres write paths.
Return the committed projection and whether the candidate was applied. Report retained state with a skipped outcome when the merge guard rejects a delayed refresh, and distinguish dry runs from accepted writes. Cover CLI output and database outcomes, including rejection by observation time when the revision and block are unchanged. Document the output fields. Validation: 54 ingest mock tests, 88 web tests, two Postgres persistence tests, package lint, and actual CLI checks against a disposable database.
matheus1lva
left a comment
There was a problem hiding this comment.
Fixes #471's core regression correctly; the ordered resolver and shared-projection design are sound.
-
Allocator regression on Gnosis and Polygon (high) — V3 vaults on chains 100 and 137 lose
vault.allocatorand all target/max ratios: the factory-derived path is deleted, and the new projection returnschain_not_configuredfor anything outside the hardcoded chain list.
Done when: a Polygon or Gnosis V3 vault with aNewDebtAllocatorlog still returns its allocator after the snapshot hook runs, or the PR states those chains are intentionally dropped.
Provenance: 12c83eb -
Transient outage blanks served data (high) — any Envio or RPC failure during the routine snapshot hook replaces a previously validated projection with an unavailable one, so the vault's allocator and every strategy ratio read null in GraphQL and REST until the next successful run. This is documented as intended, but it is an availability regression versus main, which served the address regardless of Envio.
Done when: with a validated projection stored, a hook run whose Envio call throws leaves the served allocator and ratios unchanged, at most with a stale marker.
Provenance: 12c83eb -
Unmet acceptance criterion (medium) — #471 requires shared allocator contracts and their
UpdateStrategyDebtRatioevents to be indexed in Kong; this PR delegates discovery to Envio and reads ratios as point-in-time RPC calls, without amending the issue scope.
Done when: Kong indexes shared allocator ratio events, or the issue is explicitly amended to move that out of scope.
Provenance: 12c83eb -
Missing shared-allocator multi-vault test (medium) — #471 lists "multiple vaults sharing one allocator" as a required test case; every spec uses a single vault constant.
Done when: a test resolves two vaults against the same shared allocator and asserts each projection's address and ratio calls are scoped to its own vault.
Provenance: 12c83eb -
Pagination untested (low) — the keyset cursor, stall detection, and event cap in the Envio query have no coverage; every fixture returns one page under the page size.
Done when: a test feeds more than one page and asserts the resolved allocator comes from the last page, plus one test each for the stalled-cursor and event-limit throws.
Provenance: 12c83eb -
Deployment rejection branches untested (low) — wrong factory address, vault-bound row on Katana, and ambiguous deployments are all swallowed into
allocator_configuration_unavailable, so a regression there is invisible.
Done when: tests cover each rejection branch and one valid Katana shared deployment.
Provenance: 12c83eb
How This Was Reviewed
Reviewed with the review-pr-workflow skill —
5 review lenses, each finding independently verified by claude. 1 candidate finding was refuted and dropped.
murderteeth
left a comment
There was a problem hiding this comment.
Summary
An independent multi-lens pass surfaced the same defects matheus1lva already posted (Polygon regression, outage blanking, unmet #471 criteria, missing shared-allocator and pagination tests), so those are not repeated. Two findings below: the first sharpens matheus1lva's "Unmet acceptance criterion" with replica evidence for why Envio is unnecessary, the second is new.
Issues
- packages/ingest/allocators.ts:44 - Envio is not needed; this is a Kong config gap (high) — same defect as "Unmet acceptance criterion (medium)" in matheus1lva's review, raised to high because every input the projection fetches from Envio is data Kong already knows how to index. The roleManager ABI carries
AddedNewVault,RemovedVaultandUpdateDebtAllocator, and the extractor stores every ABI event, not just hooked ones; the vault ABI carriesUpdateRoleManager; vault-bound factory deployments are already inevmlog. What Kong is missing on prod is coverage, not capability: the yvUSDC-1 role manager (0xb3bd…) predates the roleManagerFactory, so it is not athingand Kong holds zero logs from it, which is the entire #471 case; and the shared factory (0x03D4…) is not inabis.yaml. Both close with config: legacy role managers declared inconfig/manuals.yaml, the shared factory added as a source with its allocator ABI. The ordered resolver this PR adds inlib/allocators.tscan then run over Kong's ownevmlog. Instead the PR introduces a second indexer, three env vars, a 30-second external call per vault snapshot, and a projection that goes null whenever that indexer is unreachable.- Done when: allocator assignments are resolved from Kong's own
evmlogwith noENVIO_*configuration; the legacy role managers and the shared factory are indexed via config; yvUSDC-1 resolves to0x1e9eB053…from Kong data alone; andUpdateDebtAllocatorrows exist inevmlogfor chain 1. - Provenance: 12c83eb
- Done when: allocator assignments are resolved from Kong's own
- packages/ingest/allocators.ts:1 - Feature code placed at the package root (medium) — the ingest root holds only cross-cutting infrastructure (db, rpcs, prices, things, the service entry), and protocol logic lives under
abis/, withabis/yearn/lib/already serving as the shared home for Yearn modules. This PR puts three Yearn-specific files at the root instead: the projection, whose only consumer is the V3 vault snapshot hook reaching up five directory levels; the store helper, used only by the CLI; and a one-off rollout CLI, for which the repo already haspackages/scripts/src/. Anything at the root reads as shared infrastructure topackages/scriptsimporters, so this placement will be copied.- Done when: no new
.tsfiles sit at the ingest package root; the projection lives underabis/yearn/, the CLI and its store helper live underpackages/scripts/src/or beside the feature they serve, the specs follow their modules, and the docs' invocation path is updated to match. - Provenance: 12c83eb
- Done when: no new
Verdict
REQUEST_CHANGES
How This Was Reviewed
Reviewed with the review-pr-workflow skill —
5 review lenses, each finding independently verified by claude. 0 candidate findings were refuted and dropped.
Resolve assignments and factory provenance from Kong evmlog records. Remove the external indexer client, configuration, and chain allowlist. Register the legacy Yearn role manager and shared allocator factories. Discover assigned contracts from initial and replacement events, and decode shared ratio events through Kong's existing allocator ABI. Cover native log persistence, shared-vault scoping, legacy metadata, discovery hooks, and refresh behavior. Document Kong backfill steps.
Keep validated assignments and ratios during outages, with explicit stale metadata and guards against delayed recovery. Confirmed replacements and clears still replace old ratios atomically. Register Polygon's direct Role Manager and shared allocator factory for native Kong indexing. Document intentionally unsupported legacy Gnosis vaults. Move the allocator feature under the Yearn ingest directory and add SQL deployment rejection and stale-state regression coverage.
|
fixes have been applied and the description has been updated. |
|
Verified these three against the branch. All reproduce in the code as written. 1. Manager change keeps serving the old allocator (high)
The projection-level behaviour is covered at Conflating "manager not indexed" with "refresh failed" is defensible — Kong cannot see logs of an unconfigured Done when: with a validated 2. Every unmaterialized vault answers null on deploy (medium)
The removed Done when: a snapshot with a legacy 3. Raw DB and viem errors reach GraphQL clients (low)
Done when: a DB failure or malformed address on Priority: fix (1), sequence or annotate (2), (3) is a two-line wrap. |
Codex has a question: My concern with adding a legacy fallback is that the old factory-derived allocator isn't simply an older representation of the same data — it can be incorrect, which is one of the things this PR is intended to fix. I'd prefer not to knowingly preserve two conflicting sources of truth. Would you prefer that we handle this as a staged migration: deploy the new ingestion/indexing path first, backfill and verify If ingestion and web can't practically be deployed/cut over separately, would you instead prefer an explicit activation/feature gate so the new reader isn't enabled until the backfill has been verified? Or do you specifically want the legacy factory-derived allocator retained as a temporary fallback during the migration? |
|
I'll push fixes for the other 2 issues shortly |
Preserve successful finalized manager observations across later database failures. Clear the old assignment on confirmed manager changes and keep the observed block as a floor for delayed recovery, while retaining data for transient failures without a confirmed change. Mask allocator GraphQL address and database errors consistently with the vault resolver. Add projection, persistence, serving, and error-response regressions. Leave deployment sequencing for the separate rollout review.
Summary
Kong currently derives vault allocator addresses from factory logs, which misses replacements and misreads shared allocator deployments. Resolve assignments from Kong's own indexed Role Manager and vault events, then serve both GraphQL fields and snapshot ratios from the same saved projection.
Closes #471.
Indexing stays in Kong. Configure the direct Ethereum and Polygon Yearn role managers and the shared allocator factory, discover initial/replacement assigned contracts, and decode shared ratio events through the existing extractor and loader. Factory records identify deployment and ABI provenance; they do not establish assignments. No new indexing service or environment configuration is required.
Failed refreshes retain the last validated allocator and ratios with explicit
stale,lastAttemptAt, andlastErrormetadata. Confirmed replacements and clears still apply atomically. A confirmed manager change invalidates the old assignment even when the new manager has no indexed assignment; delayed jobs cannot restore the old manager at an earlier block. Old ratios never cross assignment boundaries, and delayed refreshes cannot roll back the accepted state.The allocator GraphQL resolver masks malformed-address and database errors consistently with the vault resolver, keeping diagnostic details in server logs.
How to review
Start with
docs/allocator-assignments.md,config/manuals.yaml, andconfig/abis.yaml. Follow Role Manager and shared factory discovery hooks, the combined allocator ABI, and the localevmlogqueries inpackages/ingest/abis/yearn/lib/allocators/projection.ts. The refresh CLI and writer live beside that projection. Shared serving and activation rules live inpackages/lib/allocator-snapshot.ts.The refresh CLI supports read-only checks and explicit writes, reporting the committed projection and whether it was applied, skipped, or retained with stale metadata. Required evidence failures exit nonzero even when a write records staleness.
Validation
0x71455263e2a5440fd9a9e1e4d155f237c20f703d6205883df5cedceccee45bb6and shared deployment were loaded locally. USDC-1 resolved allocator0x10BC1f4f0dDD8027264E9F10FabE7A751614C207at block 86,228,011 with on-chain ratios, including real zeros.Risk / rollout
Production backfill and activation have not been performed. Run Kong discovery/fanout for the direct managers and shared factories, replay stored manager events for historical contract discovery, and freshly extract missing shared ratio events where old ABI strides already exist. Stored-log replay cannot recover events that were never indexed. Refresh snapshots and REST caches after validating coverage.
Legacy Gnosis vaults using controllers without
getDebtAllocator(address)are intentionally unsupported. Their three vault/controller pairs and null/unavailable behavior are documented indocs/allocator-assignments.md. A legacy role-grant compatibility path is outside this PR; Gnosis factory indexing remains configured for provenance.Allocator.addressis nullable for confirmed clears or missing validated evidence. Custom assignments retain their address with unsupported/unavailable ratios. Full allocation-history APIs remain outside this PR.