This ERC defines an interface for publishing and querying subject-linked Net
Asset Value (NAV) snapshots. Each stream is keyed by (subjectId, currency) and
has one configured NAV basis. Snapshots include signed NAV, decimal precision,
valuation and publication timestamps, provider attribution, methodology
references, and correction provenance.
The core interface supports raw and staleness-aware latest-value queries,
provider-specific history, correction-chain resolution, and administrative
invalidation that preserves records while excluding invalid snapshots from
current-value queries. An optional aggregation interface defines deterministic
lower-median aggregation across provider submissions sharing a valuation
timestamp.
This ERC standardizes publication and query semantics. It does not calculate
NAV, credential providers, verify methodologies, establish asset backing, or
guarantee that NAV is an executable market or redemption price.
Motivation
Periodic valuations for funds, private credit, real estate, infrastructure,
commodities, and other illiquid or administratively priced assets differ from
continuous exchange prices. Consumers need to know what the value represents,
when the underlying valuation was measured, when it was published, who supplied
it, and whether it is too old for the intended use.
Existing price and quote interfaces do not necessarily preserve valuation
history, provider identity, methodology references, restatement provenance, or
separate publication-age and valuation-age checks. Bespoke NAV contracts also
use incompatible stream keys and latest-value semantics.
This ERC provides:
independent (subjectId, currency) NAV streams;
stream-level basis configuration preventing provider disagreement over
per-unit, per-share, or total interpretation;
provider-attributed historical snapshots;
one original provider submission per valuation timestamp;
fork-free corrections and current-chain helpers;
administrative invalidation for compromised or disputed terminal snapshots;
separate publication and valuation staleness signals; and
optional deterministic aggregation with quorum and deviation reporting.
The interface can serve vaults, settlement systems, reporting applications, and
other consumers while leaving valuation policy and provider governance to each
deployment.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
RFC 2119 and
RFC 8174.
Definitions
A stream is the namespace identified by (subjectId, currency).
A NAV basis states whether NAV represents one underlying unit, one share or
token, or the total value of the subject.
A provider is the address recorded as publishing a snapshot.
A valuation timestamp is the asserted as-of time of the valuation.
A publication timestamp is the block timestamp at which the snapshot was
recorded.
A terminal snapshot is a snapshot whose correctedByIndex equals
NO_CORRECTED_BY.
A current snapshot is a terminal snapshot that has not been invalidated.
A publication heartbeat is the maximum accepted time since publication.
A maximum valuation age is the maximum accepted time since the valuation
timestamp.
PER_UNIT represents one unit of the underlying asset. PER_SHARE represents
one share or token in a fund or pool. TOTAL represents the total NAV of the
subject.
An authorized configurer MUST call setNAVBasis before the first publication
to a stream. The function MUST:
accept only PER_UNIT, PER_SHARE, or TOTAL;
reject a stream that already contains snapshots;
reject a stream whose basis was already configured;
store the basis permanently; and
emit NAVBasisConfigured.
streamNAVBasis MUST return the configured basis or bytes32(0) for an
unconfigured stream.
publishNAV MUST reject an unconfigured stream and any supplied basis that
does not equal its configured basis.
Provider-selected basis changes are prohibited. Stream-level configuration
prevents incompatible submissions from disabling aggregation at a shared
valuation timestamp.
NAV and Decimal Semantics
The represented NAV is:
nav * 10^(-decimals)
nav is signed because liabilities can exceed assets. Consumers MUST handle
negative and zero values explicitly.
Including both chain ID and token address prevents equal addresses on different
chains from sharing a currency identifier.
Other denominations SHOULD use an application-documented, domain-separated
identifier and MUST NOT reuse an ISO code unless the denomination is that fiat
currency.
Publication Semantics
publishNAV MUST be restricted to authorized providers. Provider authorization
is implementation defined and MUST be documented.
For every accepted snapshot, the oracle MUST:
set provider to msg.sender;
set publishedAt to uint64(block.timestamp);
initialize correctedByIndex to NO_CORRECTED_BY;
append the snapshot to the stream and provider history;
update current-value and provider/timestamp indexes;
emit NAVPublished; and
return the new stream-scoped index.
valuationTimestamp MUST NOT be greater than block.timestamp.
methodologyHash MUST NOT be bytes32(0).
methodologyURI MAY be empty only when the deployment documents how consumers
retrieve the exact methodology representation out of band. The hash derivation
MUST be documented. It MAY commit to raw document bytes or a deterministic
document-bundle commitment.
The oracle MUST reject the call if block.timestamp cannot be represented as
uint64.
Provider and Valuation Uniqueness
A provider MAY publish at most one current original snapshot for an exact
stream and valuationTimestamp.
If that provider/timestamp slot is occupied, a revision MUST use correction
provenance. Other providers MAY publish independent originals for the same
stream and valuation timestamp.
Correction Semantics
An original snapshot MUST use correctsIndex == NO_CORRECTION.
A correction MUST:
identify an earlier snapshot in the same stream;
target a terminal, non-invalidated snapshot;
be published by the same provider as the target;
use the same valuationTimestamp and navBasis as the target; and
target the provider’s current snapshot for that valuation timestamp.
When accepted, the target’s correctedByIndex MUST be set to the new snapshot
index. No other target field may change.
Before invalidation, each snapshot can have at most one successor correction.
A correction can itself be corrected, creating a linear current chain. A
correction MAY change NAV, decimals, methodology, and methodology URI.
Invalidation
invalidateSnapshot MUST be restricted under a documented administrative or
governance policy. It MUST reject a zero reasonHash, unknown snapshot,
nonterminal snapshot, or already invalidated snapshot.
On success, the oracle MUST:
preserve the invalidated snapshot record;
permanently mark it invalidated;
exclude it from latest-value, provider-latest, current-chain, quorum,
aggregation, and deviation calculations defined by the optional Aggregation
Extension below;
recompute affected latest and quorum pointers; and
emit NAVSnapshotInvalidated.
If an original snapshot is invalidated, its provider/timestamp slot MUST become
available for a replacement original.
If a correction is invalidated, its direct predecessor MUST become terminal
again and the provider/timestamp slot MUST point to that predecessor. The
provider can then publish a replacement correction.
In a longer correction chain, invalidating the terminal restores only its
direct predecessor. Administrators MAY unwind additional snapshots by
invalidating each newly restored terminal in turn.
Invalidation does not erase correctsIndex history. Replacement corrections
can create multiple historical records that reference the same predecessor,
but only one non-invalidated branch can be current. Consumers reconstructing
history MUST account for NAVSnapshotInvalidated events.
An invalidated snapshot MUST NOT be corrected or restored.
isSnapshotInvalidated MUST revert for an unknown index and otherwise return
the permanent invalidation state.
Current-Chain Queries
currentSnapshotIndex MUST revert for an unknown index. It MUST follow
correctedByIndex to a terminal snapshot and return that index only if the
terminal is not invalidated. It MUST revert when no current terminal remains.
isSnapshotCurrent MUST revert for an unknown index and otherwise return
true only when the snapshot is terminal and not invalidated.
Latest NAV Queries
latestNAV MUST return the current snapshot with the greatest
valuationTimestamp, regardless of staleness. When multiple current snapshots
share that valuation timestamp, it MUST return the most recently published one;
if publication timestamps are equal, the greater snapshot index wins.
A late correction to an older valuation timestamp MUST NOT replace a current
snapshot with a later valuation timestamp as the stream’s latest NAV.
latestNAV MUST revert when no current snapshot exists.
latestNAVByProvider MUST apply the same valuation and publication ordering to
that provider’s current snapshots and MUST revert when the provider has no
current snapshot.
Historical Queries
getSnapshot MUST return the preserved record for any valid index, including a
corrected or invalidated snapshot, and MUST revert for an unknown index.
snapshotCount MUST include every published snapshot, including corrections
and invalidated records.
providerSnapshotCount and providerSnapshotAt MUST expose the provider’s
complete publication history, including corrected and invalidated snapshots.
providerSnapshotAt MUST revert for an out-of-range ordinal.
Staleness Configuration
An authorized configurer MUST be able to set a nonzero publication heartbeat
and nonzero maxValuationAge independently for each stream. Successful changes
MUST emit StalenessConfigUpdated.
heartbeat and maxValuationAge MUST return zero while the corresponding
value is unconfigured.
Configuration authorization is implementation defined and MUST be documented.
Staleness Semantics
latestNAVStatus MUST return the same snapshot selected by latestNAV plus two
independent flags:
A value is not stale exactly at its threshold boundary.
latestNAVStatus MUST revert when either staleness threshold is unconfigured or
when no current snapshot exists. It MUST NOT mutate state or emit events.
Consumers MUST evaluate both flags. Recent publication of an old valuation can
be publication-fresh but valuation-stale.
Aggregation Extension
Aggregation is OPTIONAL. An implementation supporting it MUST implement:
setAggregationConfig MUST be restricted to authorized configurers. It MUST
reject a zero quorum and a deviation threshold greater than 10,000 basis
points. Implementations MAY impose a documented maximum provider count and MUST
reject a quorum above that maximum.
Successful configuration MUST emit AggregationConfigUpdated and MUST account
for historical timestamps that already satisfy the new quorum.
quorum and deviationThreshold MUST return zero while unconfigured.
Eligible Provider Submissions
For one valuation timestamp, at most one submission per provider is eligible.
That submission is the provider’s current snapshot for the timestamp.
Corrected, invalidated, and detached historical snapshots MUST be excluded.
A valuation timestamp is aggregation-eligible when its number of eligible
providers is at least the configured quorum.
The latest aggregation timestamp MUST be the greatest eligible valuation
timestamp, not the timestamp of the most recent publication.
latestAggregationTimestamp, providerSubmissionCount,
providerSubmissionAt, and aggregatedNAV MUST revert when quorum is
unconfigured or no valuation timestamp meets quorum.
providerSubmissionCount MUST return the eligible provider count at the latest
aggregation timestamp.
providerSubmissionAt MUST return eligible submissions in provider first-seen
order for that timestamp and MUST revert when index is outside the eligible
set.
Median Aggregation
aggregatedNAV MUST normalize all eligible values to the greatest submitted
decimal precision:
normalizedNav = nav * 10^(maxDecimals - decimals)
It MUST sort normalized values in ascending order and return:
values[(providerCount - 1) / 2]
This selects the lower median for an even provider count.
The returned basis MUST equal the configured stream basis. The returned
valuation timestamp MUST equal the latest aggregation timestamp. The returned
provider count MUST equal the number of eligible submissions.
For aggregate publication staleness, publishedAt MUST be treated as the
greatest publication timestamp among eligible submissions. Aggregate valuation
staleness uses the shared valuation timestamp.
aggregatedNAV MUST revert until both staleness thresholds are configured.
Deviation Detection
After a successful publication at a valuation timestamp that meets quorum, the
non-view publication path MUST calculate:
The calculation MUST account safely for signed values. If the spread is zero,
deviation is zero. If the median is zero while spread is nonzero, or if the
calculation would overflow, deviation MUST saturate at type(uint256).max.
When deviationBps > deviationThresholdBps, the oracle MUST emit
NAVDeviationDetected from the publication transaction. Equality does not
trigger the event.
Deviation events are alerts. They do not invalidate submissions or prevent
aggregation.
Interface Detection
Compliant core oracles MUST implement ERC-165 and return true
for type(INAVSnapshotOracle).interfaceId.
Implementations supporting aggregation MUST also return true for
type(INAVAggregation).interfaceId.
ERC-165 indicates interface support only. It does not establish provider
credentials, NAV accuracy, methodology validity, liquidity, redemption rights,
or use of the oracle by a consuming contract.
Rationale
Why Key Streams by Subject and Currency?
A subject can be valued in multiple denominations. Treating each pair as an
independent stream removes ambiguity and permits separate history, staleness,
and aggregation configuration.
Why Configure NAV Basis at Stream Level?
Per-unit, per-share, and total NAV differ materially. If providers can choose
basis independently, one mismatched submission can make a quorum set
incomparable or unavailable. Immutable stream-level basis configuration rejects
the mismatch before it enters the stream.
Why Separate Valuation and Publication Timestamps?
A value can be published recently while describing an old valuation. Consumers
need both times to assess operational feed health and economic recency.
Why Signed NAV?
Liabilities can exceed assets. A signed representation avoids silently
excluding insolvent or leveraged subjects, while consumers remain responsible
for handling nonpositive values safely.
Why Corrections?
Valuations can be restated after administrator error, late information, audit
adjustments, or model changes. Correction links preserve the earlier assertion
and identify its successor.
Why Administrative Invalidation?
Correction requires the original provider. If that provider is compromised,
revoked, or unavailable, a poisoned terminal snapshot could otherwise remain
current and continue to satisfy quorum. Invalidation excludes it without
deleting history and allows a valid replacement.
Why Latest by Valuation Time?
A late correction for an older valuation should not displace a more recent
valuation as the stream’s raw latest value. Period recency and publication
recency answer different questions.
Why Lower-Median Aggregation?
Median aggregation resists a minority of extreme submissions. Selecting the
lower median for even sets makes the result deterministic without introducing
rounding between two signed values.
Why Dual Staleness?
Publication heartbeat detects a feed that stopped updating. Maximum valuation
age detects publication of economically old data. Either condition can matter
independently.
Prior Art
ERC-7726 defines a common quote interface returning the amount
of one asset in another asset’s terms. This ERC defines historical NAV
snapshots with valuation timestamps, providers, methodology, corrections,
invalidation, and staleness metadata.
ERC-4626 defines tokenized vault accounting and conversion
functions. This ERC can provide an external valuation input but does not define
vault accounting, deposits, withdrawals, or redemption guarantees.
ERC-7540 extends ERC-4626 for asynchronous requests, and
ERC-7575 supports multi-asset vaults. Both may consume NAV but
do not define this provider-attributed snapshot lifecycle.
General market-price feeds often use heartbeat and deviation mechanisms for
liquid assets. This ERC applies separate publication and valuation age to
periodic NAV and exposes methodology and correction history.
Backwards Compatibility
This ERC introduces new interfaces and does not modify existing token, vault,
oracle, or accounting standards.
Existing systems can deploy a companion oracle and map their asset or fund
identifier to subjectId. Integration is optional.
Vault integrations should not call latestNAVStatus or aggregatedNAV from
critical conversion paths unless configuration is guaranteed. These functions
revert when staleness configuration is absent. Adapters can validate and cache
an accepted NAV for non-reverting preview or conversion surfaces.
Test Cases
Implementations should test at least:
stream isolation by subject and currency;
one-time known-basis configuration and publication-before-configuration
rejection;
rejection of provider basis mismatch;
signed NAV, decimal, magnitude, and future-valuation bounds;
methodology hash requirements and documented empty-URI behavior;
provider/timestamp original uniqueness;
correction provider, timestamp, basis, terminal, and latest-slot guards;
correction-of-correction chains and current-state helpers;
latest selection by valuation timestamp rather than publication order;
provider history including corrected and invalidated records;
publication and valuation staleness before, at, and after each boundary;
staleness-aware query rejection while unconfigured;
original and correction invalidation;
predecessor restoration and replacement publication after invalidation;
latest-provider, latest-stream, and quorum recomputation after invalidation;
aggregation configuration and historical quorum discovery;
provider caps and quorum limits;
decimal normalization and lower-median selection;
latest eligible valuation-timestamp selection;
provider submission pagination and ordering;
corrected and invalidated submission exclusion;
deviation threshold, zero-median, and overflow saturation behavior;
fiat and token currency derivation; and
positive and negative ERC-165 detection.
Reference Implementation
A Solidity reference implementation, constants library, unit tests, Medusa
property tests, deployment configuration, and independent audit are linked from
the official discussion thread.
The reference implementation:
uses provider, configurer, and administrator roles;
supports all core and aggregation functions in one contract;
caps providers per valuation timestamp at 64;
uses deterministic lower-median aggregation;
emits deviation alerts from publishNAV; and
recomputes affected indexes after administrative invalidation.
Role assignments and the provider cap are reference deployment choices. The
stream basis, correction, invalidation, staleness, and deterministic aggregation
semantics are requirements of this ERC.
Security Considerations
NAV Is Not an Executable Price
NAV is an accounting or valuation assertion. A token can trade above or below
NAV, and redemption can be gated, delayed, limited, or unavailable. Consumers
must not treat NAV as a liquid market price without separately validating
liquidity and redemption assumptions.
Provider and Configurer Trust
A provider can publish fabricated or mistaken values and methodologies. A
configurer can choose unsafe staleness or quorum settings. Implementations must
document authorization, governance, upgrade, and key-management policies.
Revoking a provider role does not invalidate its existing snapshots. An
authorized invalidator must separately invalidate any snapshot that should no
longer participate in current queries.
Methodology Verification
A methodology hash is useful only when consumers can obtain the committed
document representation and reproduce the hash. An empty or unavailable URI
can make independent verification impossible unless an out-of-band retrieval
process is documented.
Staleness Enforcement
Staleness flags protect only consumers that check them. latestNAV deliberately
returns raw data without a staleness decision. Pricing and settlement paths
should use validated status or a controlled adapter.
Negative and Zero NAV
Consuming contracts that assume positive NAV can underflow, divide by zero, or
misprice assets. They must define explicit behavior for zero and negative
values.
Provider Collusion and Correlated Error
Median and quorum reduce single-provider influence but do not prevent collusion,
shared data-source failures, or common methodology errors. Address count does
not prove provider independence.
Invalidation Authority and Cost
Invalidation can remove legitimate data and change latest or aggregate values.
The authority should be strongly controlled and every reason commitment should
be independently reviewable.
Recomputing latest and quorum pointers can require work proportional to stream
history. Production implementations with long histories should use bounded or
checkpointed indexing while preserving the specified results.
Correction and Invalidation Interpretation
Invalidation can detach a historical correction and permit a replacement branch.
Consumers must combine correction pointers with invalidation state and events;
following correctsIndex alone does not identify the current branch.
Front-Running Valuation Updates
Material NAV changes visible before inclusion can enable transactions against
an older accepted value. Deployments should consider private submission,
commit-reveal publication, settlement pauses, or delayed activation when the
economic risk justifies the complexity.
Timestamp Dependence
Valuation timestamps are provider assertions, and staleness uses
block.timestamp. Block producers can influence timestamps within protocol
bounds. Consumers must account for this uncertainty.
Decimal Normalization
Aggregation multiplies lower-precision signed values. Implementations must
enforce the numeric bounds in this ERC before normalization and use checked
arithmetic.
Privacy and Commercial Sensitivity
Methodology URIs, valuation timing, and provider behavior can reveal sensitive
fund or asset information. Deployments should avoid publishing confidential
documents or predictable private references on public chains.