ERC-8330: Subject-Linked NAV Snapshot Oracle

We would like feedback on ERC-8330 — Subject-Linked NAV Snapshot Oracle, a draft ERC for publishing and querying provider-attributed Net Asset Value snapshots for application-defined subjects.

Update — July 09, 2026: ERC number has been allocated. The ERC remains in Draft status and may change based on review.

Formal ERC PR: ethereum/ERCs#1858
Spec file: ERCS/erc-8330.md


Periodic NAV for funds, private credit, real estate, infrastructure, commodities, and other illiquid or administratively priced assets differs from a continuous market-price feed. A consumer needs to know what the value represents, its denomination, when the valuation was measured, when it was published, who supplied it, which methodology was used, and whether either time is too old for the intended use.

Each stream is keyed by (subjectId, currency) and has one immutable configured NAV basis: per underlying unit, per share or token, or total subject value. Configuring the basis at stream level prevents providers from submitting incomparable interpretations into the same aggregation set.

The core interface provides:

  • signed NAV with explicit decimal precision;
  • provider and methodology attribution;
  • distinct valuation and publication timestamps;
  • one original provider submission per valuation timestamp;
  • linear correction chains;
  • administrative invalidation that preserves history;
  • stream-wide and provider-specific latest-value queries; and
  • independent publication-heartbeat and valuation-age status.

Invalidation is separate from correction because a compromised, revoked, or unavailable provider may be unable to correct a poisoned terminal snapshot. Invalidating a terminal correction restores its direct predecessor as current and allows a replacement correction, while retaining every historical record and invalidation event.

An optional aggregation interface selects the greatest valuation timestamp that currently satisfies quorum, normalizes provider values to common decimal precision, and returns the deterministic lower median. It also exposes eligible provider submissions and emits deviation alerts. Aggregation does not prove provider independence or valuation correctness.

Scope boundaries

ERC-8330 standardizes publication and query semantics. It does not:

  • calculate or independently verify NAV;
  • credential providers or validate methodologies;
  • establish asset ownership or backing;
  • guarantee liquidity or redemption rights;
  • make NAV an executable market price; or
  • ensure that a consuming contract checks staleness or aggregation results.

latestNAV deliberately exposes the raw latest current snapshot. Staleness-sensitive consumers should use latestNAVStatus, an aggregate, or a controlled adapter and evaluate both age signals.

Questions for review

  1. Is immutable stream-level NAV basis the right safeguard against incomparable provider submissions?

  2. Are provider-and-valuation uniqueness plus linear corrections sufficient for restatement history?

  3. Is administrative invalidation necessary for compromised-provider recovery, and are predecessor-restoration semantics understandable to consumers?

  4. Should publication age and valuation age remain separate mandatory signals?

  5. Is the lower median the appropriate deterministic aggregation rule, especially for even provider counts and signed values?

  6. Should aggregation remain an optional interface, or is it central enough to belong in the core?

  7. Does the term “oracle” communicate the interface accurately given the explicit distinction between reported NAV and executable price?

Implementation status

A Solidity reference implementation and test suite is available in the reference repository.

An example UI suite is also available for non-normative exploration of the interface and its role in the broader titled-asset standards family.

The audited reference commit is caa9b05. It includes unit tests, Medusa property tests, deterministic aggregation, and invalidation coverage. The implementation has also been reviewed in an independent Verichains audit.

ERC-8330 is independently deployable and does not require a particular token or vault standard. It was introduced alongside five other standalone draft ERCs in the architecture discussion, but those interfaces are not dependencies.

Authorship

Chris Turner, David Hay (LinkedIn), Reagan Simpson, and Collins Musyimi.

Developed at Kula, which builds infrastructure for regulated virtual-asset and titled-asset use cases. Reference implementations are open-source; we are proposing ecosystem interfaces, not a Kula-only stack. We are open to additional co-authorship and community contribution beyond Kula.

4 Likes

Quick update for reviewers: we have a non-normative UI suite and an ERC-specific architecture view.

These are intended to make the NAV snapshot model easier to inspect in context, including provider attribution, valuation and publication timestamps, staleness, correction chains, invalidation, and optional aggregation.

The UI is backed by the open-source reference implementation, but it is only an explanatory/demo layer; the ERC text remains normative.

Feedback on valuation-time semantics, provider attribution, staleness, correction and invalidation handling, and the optional aggregation extension would be very welcome.

Hello @redcoat,

Thanks a lot for this ERC, great job on that!

I would be interested to have some guideline on how this ERC could be used with an ERC-20 or an ERC-721, which are also sometimes used to represent financial assets (eventually).

Use case example:

If I have a money market fund represented by an ERC-20, how I can use this ERC (if it makes sense to use it) to represent the NAV in my ERC-20 ?

Also, maybe it could be worth to add the integration guideline for an ERC-4626 vault directly in the ERC ?

See titled-asset-standards/packages/erc-nav-oracle at main · KulaDao/titled-asset-standards · GitHub

Best!

2 Likes

@AccessDenied403 Thank you, happy to provide some high-level guidance. ERC-8330 is intentionally token-standard-neutral: it publishes and makes a NAV history queryable, but does not itself change an ERC-20 balance, an ERC-721 ownership record, or an ERC-4626 exchange rate.

For an ERC-20 money-market-fund token, a deployment would normally define the fund as the subjectId, select the currency and stream-level NAV basis (for example, NAV per share/token), and have its issuance, redemption, or settlement logic query a validated ERC-8330 result. The token’s ordinary transfer function does not need to depend on the NAV oracle unless the deployment deliberately makes it part of transfer or settlement policy.

For an ERC-721 representing a unique asset or position, the subjectId can identify that asset or position and the stream can report total-subject NAV. ERC-8330 does not imply that an NFT’s market price equals that reported NAV; it supplies a provider-attributed valuation record that an application may use.

ERC-4626 is a particularly useful integration case, but it needs care. ERC-8330 can be an input to a vault’s pricing or settlement process, while the vault remains responsible for its own asset-accounting, fees, liquidity, rounding, and conversion semantics. As the reference guidance notes, a vault should not directly make its conversion paths depend on an unconfigured or stale oracle call. An adapter or validated cached NAV is generally safer, with stale/unconfigured handling occurring in explicit subscription, redemption, or settlement flows.

1 Like

Status update: ERC-8330 is now in Last Call through October 19, 2026. Focused technical feedback on the specification remains very welcome.

Last Call feedback on ERC-8330. Correction chains and invalidation cover a provider fixing its own snapshot, but I could not find a way for a consumer to tell a snapshot that is still open to challenge from one that is final. Resolution systems show why it matters: from 1 Jan to 2 Oct 2026 there were 3,005 disputes on 2,666 Polymarket markets, and of 2,543 settled disputed markets, 853 (33.5%) settled differently from the disputed proposal. A consumer that read the early value read something that was later superseded.

Suggestion: an optional per-snapshot status (proposed, disputed, final) plus a finalizedAt timestamp, and a minStatus argument on the latest-value queries. A redemption flow could then require final, while a dashboard reads proposed. It would also help to state whether invalidating a terminal correction can restore a predecessor that was never final.

Sample of a signed timeline with this shape: Settlement Risk sample pack · Predge

1 Like

@predge-ai Thank you - this identifies an important distinction between a snapshot that is current in the ERC-8330 correction and invalidation history, and one that a particular deployment considers settled or no longer open to challenge.

ERC-8330 intentionally standardizes the former. A current snapshot is the latest non-invalidated terminal record; it is not represented as legally final, dispute-free, audited, or automatically suitable for redemption. heartbeat and maxValuationAge address freshness, not dispute resolution.

The invalidation behavior is already specified: if a terminal correction is invalidated, its direct predecessor becomes terminal/current again. That restores an available historical record, rather than asserting that the restored value is economically final.

We agree that deployments needing a challenge period or settlement-finality gate need an explicit additional layer. We would be cautious about adding proposed / disputed / final states and minStatus to the core, because that requires a standardized dispute authority, evidence model, resolution process, and finality rules that will vary materially by product and jurisdiction.

A separate optional settlement/finality extension could be useful if there is broader demand for an interoperable query surface. We will clarify the distinction in the ERC text.

Agreed, keep the ERC-8330 core clean. “current” as the snapshot’s own state is the right scope, and settlement or finality belongs in something a reader opts into. Thanks for clarifying the text.

If there is interest, I can sketch a minimal optional extension in a separate thread: one view returning the finality state, a finalizedAt, and a reference to the authority that finalized it (an oracle request, an adapter or a registry entry), with no dispute process standardised. Implementations without a finality notion simply would not support it.

2 Likes

Why does aggregate publication freshness use the newest submission rather than require a fresh quorum?

Suppose quorum is three and all three submissions have exceeded the publication heartbeat. One provider then publishes a correction for the same valuation timestamp. Would that make isPublishStale false even though the other two providers remain silent?

The valuation-age check still limits the age of the underlying NAV. But within that limit a single provider could keep the aggregate publication-fresh. Should consumers get a separate fresh-provider count to distinguish one active publisher from a fresh quorum?

1 Like

@SergeevDmitry Good catch. Under the current wording, the answer is yes: one provider’s correction can make aggregate isPublishStale false because aggregate publication freshness uses the most recent eligible publishedAt, even while other submissions contributing to the median remain past their heartbeat.

That is not the assurance the flag should convey. A fresh quorum is distinct from an aggregate composed entirely of fresh inputs, and the latter is the safer default for the current aggregation model: stale submissions still influence the median.

We will revise the aggregation semantics so that isPublishStale is true when any eligible submission at the aggregation timestamp is publication-stale, equivalently using the oldest eligible publishedAt. Consumers that want to aggregate only a fresh subset can apply a separately documented selection and aggregation policy.

This is a normative change, so we will return ERC-8330 to Review rather than make it during Last Call.

1 Like

Thanks again to @SergeevDmitry for identifying this issue.

The resulting change has now been merged in ethereum/ERCs#2116, returning ERC-8330 to Review. The open-source Solidity reference implementation has been updated to the same fresh-quorum model and is available in KulaDao/titled-asset-standards#42 and the UI Suite linked above.

This goes further than our October 14 response in post 10. That response would have made aggregate isPublishStale true when any eligible submission was publication-stale, while still leaving those submissions in the median. On further review, a flag was not a strong enough guarantee, because stale inputs would still have moved the result.

The revised aggregate uses only provider submissions whose publishedAt is no more than the configured maxSubmissionAge before block.timestamp. maxSubmissionAge is independent of the stream heartbeat. aggregatedNAV is available only when the latest aggregation timestamp has at least the configured quorum of those fresh submissions. Otherwise the call reverts. It does not fall back to an older valuation timestamp that still has a fresh quorum.

The merged interface changes are:

  • isPublishStale has been removed from the aggregatedNAV return values.

  • The return tuple is now (nav, decimals, navBasis, valuationTimestamp, freshProviderCount, isValuationStale).

  • freshProviderSubmissionCount(subjectId, currency) returns the number of currently fresh contributors at the latest aggregation timestamp.

  • freshProviderSubmissionAt(subjectId, currency, index) exposes those fresh submissions.

  • setAggregationConfig and AggregationConfigUpdated now include maxSubmissionAge, and maxSubmissionAge(subjectId, currency) exposes the configured window.

latestNAVStatus() still reports stream-level publication staleness from heartbeat. A successful aggregatedNAV does not mean that flag would be false.

maxSubmissionAge should exceed the expected maximum publication spread between the providers required for quorum. If the spread is greater than the window, an early submission can age out before the final required provider publishes. The valuation timestamp can then have a historical quorum without a fresh quorum at that moment.

The result is intentionally time-dependent. Freshness is evaluated at query time using block.timestamp. As individual submissions age beyond maxSubmissionAge, the contributor set can shrink, the lower median can change while fresh quorum remains, and aggregatedNAV reverts once fresh quorum is lost.

This is independent of valuation staleness. An aggregate can have a fresh quorum while its shared valuation timestamp is economically old, so an available result can still return isValuationStale = true.

The revision also changes the INAVAggregation ERC-165 interface ID. aggregatedNAV(bytes32,bytes32) keeps its function selector, but the return tuple is ABI-incompatible with the earlier draft. A decoder from that draft can read the old providerCount as freshProviderCount and the old isPublishStale as isValuationStale. Integrations need to verify support for the revised interface ID before decoding the response. The setAggregationConfig selector changed as well.

1 Like

Requiring a fresh quorum and excluding stale inputs addresses the issue I raised. The separate valuation-age check also matters since recently published data can still describe an old valuation. Thanks for carrying this through into the specification and implementation.

1 Like