hidden fundsAptos · Movement

What counts as “left behind”

This is the contract every source and every total follows. A source that cannot meet it is not counted.

Inclusion rules

A position counts only if all hold:

Excluded: active stake, requests that have not matured, live LP/lending, wallet tokens that have a market.

Stranded liquid receipt tokens

A wallet-held receipt token counts only if all of these hold:

It is valued at redemption payout.

The market test:

Aging

Each position has a claimableSince and an ageBasis, taken from the first one available:

ageBasis Meaning Headline
onchain_maturity On-chain unlock, maturity, lock expiry or vesting release time yes
protocol_closure Effective time of protocol closure or deprecation, with evidence yes
position_interaction Last protocol interaction with this position (its object, ticket or profile); never general wallet activity no — estimated; shown separately unless the source documents it as a conservative bound
unknown None of the above no — excluded from all age buckets

The age buckets are cumulative: ≥ 30, ≥ 90, ≥ 180 days. The headline uses ≥ 90 days.

Accounting

Per position:

Field Meaning
id source:owner:locator:positionKind[:asset]
parentId source:owner:locator, used for grouping
owner 32-byte address that can sign recovery. Objects resolve through the ObjectCore owner chain (cycle detection, depth ≤ 8). An owner with no signer path → unknown with blocker unsupported_owner.
positionKind principal, fees, reward or request
grossClaim[] What the contract records as owed, raw units per asset
expectedPayout[] What recovery pays now (reserve-limited, net of fees); payoutBasis is view, derived or simulated
recoverableUsd expectedPayout × price. priceSource and priceAt are stored; quotes older than 7 days are unpriced; unpriced value is counted separately, never as 0. Prices are CoinGecko quotes checked against the exact asset, except staked-APT receipts without a fresh quote (stAPT, sthAPT): those are valued at redemption, the on-chain exchange rate (less any unstake fee) × the APT quote, dated like the APT quote and labeled derived.
status Exactly one of recoverable, team_gated (needs an operator signature or packet), blocked (with blockers[{code, detail}]), unknown
confidence verified_view, derived_math or indexer_only. indexer_only never enters totals.

Dedupe:

Headline = recoverableUsd where all of these hold:

Face value, blocked, team_gated, estimated-age and unpriced value are reported separately.

Snapshots

Snapshots are not atomic. Each source records:

“Complete” means complete within a named enumeration scope, never chain-wide.

A known non-zero position is re-read in the run after its on-chain record changes, and in any case at least monthly. Most sources (native staking, LST requests, Thala) re-read every run. A change is anything the source’s enumeration sees: a new entry-function call (including exits, claims and withdrawals), a changed table row or hint, or an owner that drops out of a full scan. The monthly re-reads are spread over four weekly runs. A position that changes without any on-chain record (for example a value that drifts with a price) can therefore be up to 35 days old; each source page shows when it was read. Recent activity only sets the order of reads, never whether a position is correct.

This page is docs/left-behind.md, rendered from the code repository.