3. Evidence System
3.1 Evidence Unit Schema
An Evidence Unit is a single observation with provenance. Evidence without provenance is not admissible.
{
"evidenceId": "string // Content-addressed (Keccak-256 of canonical form)",
"type": "EvidenceSourceType",
"source": "string // Declared source (e.g., 'solana-mainnet-rpc')",
"retrievalMethod": "string // How evidence was obtained",
"anchor": {
"block": "number // Block/slot number",
"slot": "number | null // Solana slot (if applicable)",
"time": "string // ISO 8601 timestamp"
},
"integrity": {
"hash": "string | null // Content hash of canonical form",
"signature": "string | null // Provider signature (if available)"
},
"canonicalForm": "bytes // BCE-encoded content (Section 3.4)",
"rawResponse": "bytes | null // Original provider response (for audit)",
"ref": "string // Reference URI for independent retrieval (see below)"
}
ref Field Specification (for independent validator retrieval):
The ref field MUST contain sufficient information for a validator to independently retrieve the same evidence from the original source. Combined with retrievalMethod and anchor, this enables trustless replay verification (Section 7.2, Step 2).
| Evidence Class | ref Format |
Example |
|---|---|---|
| ONCHAIN (Solana) | solana://{cluster}/{method}?params={url-encoded-json} |
solana://mainnet/getTokenAccountsByOwner?params=["AcAddr",{"mint":"MintAddr"},{"encoding":"jsonParsed"}] |
| ONCHAIN (EVM) | evm://{chainId}/{method}?params={url-encoded-json} |
evm://1/eth_call?params=[{"to":"0x...","data":"0x70a08231..."},"0xF4240"] |
| OFFCHAIN_PINNED | https://{source-domain}/{path} |
https://api.dexscreener.com/latest/dex/tokens/{addr} |
| OFFCHAIN_EPHEMERAL | social://{platform}/{post-id} |
social://twitter/1234567890 |
For ONCHAIN evidence, the anchor.block / anchor.slot field specifies the exact historical state to query. Validators reconstruct the RPC call as: RPC_CALL(ref.method, ref.params, at_block=anchor.block).
For OFFCHAIN evidence, ref is informational — the original source may no longer serve the same data. Validators fall back to operator-served or decentralized storage copies, verified by integrity hash only.
3.2 Evidence Source Type Taxonomy
EvidenceSourceType = ONCHAIN_STATE | TX | EVENT | CODE | OFFCHAIN_DECLARED
Detailed Source Registry:
| Source Type | Chain | Description | Retrieval |
|---|---|---|---|
ACCOUNT_BALANCE |
Solana | SPL token balance at slot | getTokenAccountsByOwner |
ACCOUNT_BALANCE |
EVM | ERC-20 balance at block | eth_call(balanceOf) |
TOKEN_SUPPLY |
Solana | Total supply at slot | getTokenSupply |
TOKEN_SUPPLY |
EVM | Total supply at block | eth_call(totalSupply) |
TOKEN_METADATA |
Solana | Metaplex metadata (name, symbol, URI) | getAccountInfo |
TRANSFER_EVENT |
Solana | SPL Transfer instruction log | getTransaction logs |
TRANSFER_EVENT |
EVM | ERC-20 Transfer event log | eth_getLogs |
POOL_RESERVES |
Solana | AMM pool state (reserves, sqrt_price) | getAccountInfo |
POOL_RESERVES |
EVM | Uniswap/DEX pool reserves | eth_call(getReserves) |
PROGRAM_DATA |
Solana | Account data / IDL-decoded state | getAccountInfo |
CONTRACT_CODE |
EVM | Contract bytecode at block | eth_getCode |
TX_RECEIPT |
All | Full transaction with status and logs | getTransaction |
SOCIAL_POST |
Off-chain | Twitter/X post with engagement metrics | API or scrape |
SOCIAL_ENGAGEMENT |
Off-chain | Aggregated social metrics | API |
DEX_SCREENER_DATA |
Off-chain | Market data from DexScreener | API / scrape |
3.3 Off-Chain Evidence Lifecycle
Off-chain evidence (SOCIAL_POST, SOCIAL_ENGAGEMENT, DEX_SCREENER_DATA) is fundamentally different from on-chain evidence: it is mutable at source, ephemeral, and cannot be independently re-fetched at a later time. Tweets get deleted, engagement metrics fluctuate, DexScreener data changes. This creates a tension with replay reproducibility that the protocol resolves through mandatory snapshot-and-store semantics.
Snapshot-at-Collection Rule:
For all OFFCHAIN_DECLARED evidence types:
- The
canonicalFormis captured once at evaluation time and becomes the immutable snapshot. It represents the state of the off-chain source at the moment of collection, not at any later time. - The
rawResponsefield is mandatory (not optional as for on-chain evidence). The raw API response or page content MUST be preserved for audit. - After canonicalization, the
evidenceId = Keccak-256(canonicalForm)permanently identifies this specific snapshot. - The original source is not re-queried during replay. Validators use the stored
canonicalFormexclusively. - The
anchor.timefield records the ISO 8601 timestamp of when the snapshot was taken. For off-chain evidence,anchor.blockis set to the nearest Solana slot atanchor.time(for temporal ordering within the evidence graph).
Mandatory Storage for Off-Chain Evidence:
Because off-chain evidence cannot be re-fetched, it MUST be promoted to decentralized storage (IPFS/Filecoin) immediately upon VO creation — not after anchoring. This is stricter than the 24-hour window for on-chain evidence (Section 8.5), because on-chain evidence can be re-derived from archive nodes as a fallback.
| Evidence Class | Re-fetchable? | Storage Requirement | Replay Source |
|---|---|---|---|
| ONCHAIN | Yes (from archive RPC) | Standard tiered (Section 8.5) | Independent re-fetch or stored copy |
| OFFCHAIN_PINNED | Partial (source may change) | IPFS immediately on VO creation | Stored copy only, hash-verified |
| OFFCHAIN_EPHEMERAL | No (source may be deleted) | IPFS immediately on VO creation + Arweave within 7 days | Stored copy only, hash-verified |
Impact on Replay Trust:
Validators replaying a VO with off-chain evidence MUST understand that they are verifying computational correctness (the engine processed this evidence correctly) but NOT observational correctness (the evidence accurately reflected reality at collection time). This distinction is reflected in the qualification rules (Section 6.2).
BCE Specifications for Off-Chain Evidence Types:
SOCIAL_POST:
canonicalForm = BCE_ENCODE({
author: string, // username / handle
content: string, // full post text (UTF-8)
engagement: {
likes: u64,
reposts: u64,
replies: u64,
views: u64
},
platform: string, // 'twitter' | 'telegram' | etc.
postId: string, // platform-specific post identifier
publishedAt: string, // ISO 8601 (post creation time)
snapshotAt: string // ISO 8601 (when this snapshot was taken)
})
DEX_SCREENER_DATA:
canonicalForm = BCE_ENCODE({
pairAddress: bytes32, // pool/pair address
baseToken: bytes32, // base token mint
quoteToken: bytes32, // quote token mint
priceUsd: fixedpoint64, // price in USD (scale 10^8)
volume24h: u64, // 24h volume in lamports
liquidity: u64, // total liquidity in lamports
txCount24h: u64, // 24h transaction count
snapshotAt: string // ISO 8601 (when this snapshot was taken)
})
Note: snapshotAt is included in the canonical form (unlike constructionTime in graph metadata) because the exact moment of off-chain observation is semantically meaningful — the same source queried 5 minutes later may return different data.
3.4 Baseline Canonical Encoding (BCE)
Reproducibility depends on canonicalization. Different RPC providers return structurally equivalent but byte-different responses for the same on-chain state.
BCE transforms raw evidence into a provider-independent representation:
Step 1: Strip provider-specific metadata
- Remove
jsonrpc,id, provider headers - Remove non-deterministic fields (request timing, node version)
Step 2: Normalize type representations
- Integers: Fixed-width encoding (
u64for Solana lamports,u256for EVM amounts) - Addresses: Fixed-length bytes (32 bytes for Solana, 20 bytes for EVM)
- Booleans: Single byte (
0x00or0x01) - Strings: UTF-8 with explicit length prefix
- Null: Distinguished null byte (
0xFF)
Step 3: Order fields deterministically
- All object fields sorted lexicographically by key (UTF-8 byte order)
- Arrays maintain original index order
Step 4: Serialize to deterministic binary
- Use a canonical binary format (similar to borsh or CBOR canonical mode)
- No optional padding, no alignment bytes
Step 5: Compute content hash
evidenceId = Keccak-256(canonicalForm)
BCE Specification per Evidence Type:
ACCOUNT_BALANCE:
canonicalForm = BCE_ENCODE({
account: bytes32, // account address (fixed 32 or 20 bytes)
mint: bytes32, // token mint
balance: u64, // raw integer (lamports / wei)
slot: u64 // block/slot number
})
POOL_RESERVES:
canonicalForm = BCE_ENCODE({
pool: bytes32, // pool address
tokenA: bytes32, // token A mint
tokenB: bytes32, // token B mint
reserveA: u128, // reserve of token A
reserveB: u128, // reserve of token B
slot: u64 // block/slot number
})
Cross-Provider Reconciliation
When evidence is retrieved from multiple providers for the same anchor point, the system MUST:
- Canonicalize each response independently
- Compare content hashes
- If hashes match, evidence is confirmed
- If hashes differ, flag as
PROVIDER_DIVERGENCEand require manual resolution or majority consensus among 3+ providers
3.5 Provenance Requirements
Every evidence unit MUST satisfy:
- Source reference: A declared source that an independent party can query
- Retrieval method: Sufficient detail to reproduce the same query
- Temporal anchor: A specific block/slot that the data is pinned to
- Integrity guarantee: Content hash of canonical form
Additional requirements for OFFCHAIN_DECLARED evidence:
- Raw response:
rawResponsefield is mandatory (not optional). The complete API response or page content MUST be stored. - Snapshot timestamp:
anchor.timerecords the exact collection moment;canonicalFormincludes asnapshotAtfield. - Staleness limit: Off-chain evidence is inadmissible if
anchor.timediffers from the VO's evaluation start time by more than 5 minutes. This bounds the window in which the off-chain source could have changed between snapshot and evaluation. - Source liveness: At evaluation time, the system MUST verify the source was accessible (HTTP 200 or equivalent). If the source returns an error, the evidence unit is recorded with
rawResponsecontaining the error and is inadmissible.
Evidence failing any of these requirements is inadmissible. Claims depending on inadmissible evidence cannot cross the line.