const address = value => typeof value === 'string' && /^0x[a-f0-9]{40}$/i.test(value); const observed = item => item?.status === 'available' ? String(item.value) : 'Unavailable'; const shown = value => value == null ? 'Unavailable' : String(value); // Compare observations, not a promise that no intervening changes occurred. export function compareEvidence(before, after) { for (const report of [before, after]) { if (report?.kind !== 'token_intelligence' || report.network !== 'robinhood-mainnet' || report.chainId !== 4663 || !address(report.address) || !report.contract || !Array.isArray(report.coverage) || !Number.isFinite(Date.parse(report.observedAt))) throw new Error('Choose two RH contract-intelligence reports with valid observation times.'); } if (before.address.toLowerCase() !== after.address.toLowerCase()) throw new Error('Evidence must refer to the same RH contract.'); if (Date.parse(after.observedAt) <= Date.parse(before.observedAt)) throw new Error('The new observation must be later than the saved baseline.'); const changes = []; const field = (name, a, b, scope) => { if (a !== b) changes.push({ field: name, before: a, after: b, scope }); }; const a = before.contract, b = after.contract; field('Raw supply', shown(a.rawSupply), shown(b.rawSupply), 'Contract-reported totalSupply()'); field('Decimals', shown(a.decimals), shown(b.decimals), 'Contract-reported decimals()'); field('Owner interface', observed(a.owner), observed(b.owner), 'owner() only; other roles are not enumerated'); field('Pause interface', observed(a.paused), observed(b.paused), 'paused() interface observation'); field('Contract code size', shown(a.codeBytes), shown(b.codeBytes), 'Byte count only; equal size does not prove equal code'); field('Contract runtime SHA-256', shown(a.codeSha256), shown(b.codeSha256), 'Hash of observed runtime bytes, not a source-code audit'); field('Implementation runtime SHA-256', shown(a.proxy?.targetCode?.value?.sha256), shown(b.proxy?.targetCode?.value?.sha256), 'First resolved implementation only, at each report block'); for (const key of ['implementation', 'admin', 'beacon']) field(`Proxy ${key}`, observed(a.proxy?.[key]), observed(b.proxy?.[key]), 'EIP-1967 storage observation'); field('Minimal proxy target', shown(a.proxy?.minimalProxyTarget), shown(b.proxy?.minimalProxyTarget), 'Recognized exact minimal-forwarding runtime patterns'); const oldPool = before.markets?.primary, newPool = after.markets?.primary; field('Primary indexed pool', shown(oldPool?.address).toLowerCase(), shown(newPool?.address).toLowerCase(), 'A different selected pool is not a liquidity movement'); // Compare liquidity only when the same identified pool was observed twice. if (oldPool?.address && newPool?.address && oldPool.address.toLowerCase() === newPool.address.toLowerCase()) field('Reported pool liquidity / USD', shown(oldPool.liquidityUsd), shown(newPool.liquidityUsd), 'Third-party pool estimate; both sides included'); const ids = new Set([...before.coverage, ...after.coverage].map(c => c.id)); for (const id of ids) field(`Coverage: ${id}`, shown(before.coverage.find(c => c.id === id)?.status), shown(after.coverage.find(c => c.id === id)?.status), 'Availability of this source or check'); return { kind: 'evidence_comparison', network: 'robinhood-mainnet', chainId: 4663, address: after.address, baselineId: before.id, currentId: after.id, baselineAt: before.observedAt, observedAt: after.observedAt, changes, limitations: ['This compares two selected observations, not every block between them.', 'No listed change does not establish unchanged bytecode, permissions, holdings, or transfer behavior.', 'Saved reports are local, unsigned browser records. This comparison is not an attestation or a signing authorization.'] }; } export function latestBaseline(history, current) { return history.filter(r => r?.kind === 'token_intelligence' && r.network === 'robinhood-mainnet' && r.chainId === 4663 && typeof r.address === 'string' && r.address.toLowerCase() === current.address?.toLowerCase() && Date.parse(r.observedAt) < Date.parse(current.observedAt)) .sort((a,b) => Date.parse(b.observedAt) - Date.parse(a.observedAt))[0]; }