# Vaultfire — V2 Compatibility Matrix (PR1 revised)

**Prepared:** 2026-08-20
**Repo HEAD:** `a80144d1acbbbbf24b9eca7cd91e61daad0c0ad6`
**Purpose:** Enumerate every V2 surface (contracts, ABIs, events, API routes, SDK methods, x402 routes, indexer expectations) that must remain intact during and after V3 migration. This is the "V2 preservation contract."

Assignment rules being enforced here:
- Never change deployed V2 bytecode.
- Preserve V2 ABIs, addresses, events, historical data, read endpoints.
- Add V3 interfaces under a separate namespace; do not reuse V2 events with changed meanings.
- Preserve current V2 API routes and response schemas; only add optional fields.
- Preserve current V2 SDK methods; require callers to explicitly choose V3 for new money-moving actions.

---

## 1. Deployed contracts (frozen)

**Total instances:** 134 (36 unique names × 4 EVM chains, plus a few Base-only contracts). Solana appears only as an x402/read surface — no Solana contracts.

Canonical source: `baseline/deployments.json`. Every SDK constant, website address, docs page, and explorer link must be generated from this file.

### Per-chain counts

| Chain | Contract instances | Unique names | Notes |
|---|---:|---:|---|
| Base (8453) | 36 | 36 | Only chain with `VaultfireBIPVault`, `VaultfireBatchOnboarder`, `VaultfireStreetCred` |
| Avalanche C-Chain (43114) | 32 | 32 | Missing `VaultfireBIPVault`, `VaultfireBatchOnboarder`, `VaultfireStreetCred`, `VaultfireNameService` |
| Arbitrum One (42161) | 33 | 33 | Missing `VaultfireBIPVault`, `VaultfireBatchOnboarder`, `VaultfireStreetCred` |
| Polygon PoS (137) | 33 | 33 | Same shape as Arbitrum |
| Solana | 0 contracts | — | x402 payment rail (`payToSolana`) and read endpoints only |

### Bytecode-identical vs chain-forked contracts

Of the 36 unique names, 13 have byte-identical bytecode across all chains they appear on (safe to treat as a single ABI). The other 20 have chain-specific bytecode forks; each instance must be treated as its own ABI target until diff is proven zero. Details in `baseline/onchain_fetch_report.json`.

### Contract-status field (must be added to `deployments.json`)

Per assignment §Contracts, every entry must carry one of:
- `active` — live V2, indexed, integrated
- `legacy` — pre-V2 or pre-audit contract that we still read
- `deprecated` — being sunset
- `paused` — Pausable-set contracts currently paused
- `read-only` — kept for provenance only; no new writes

PR1 exit criterion: this field is added to every entry in `deployments.json`.

---

## 2. ABIs and events (preserved verbatim)

Per assignment: "Preserve V2 ABIs in a legacy/v2 package. Add V3 interfaces under a separate namespace. Do not reuse V2 events with changed meanings."

### Star bond ABIs

**`AIAccountabilityBondsV2`** — public/external functions (source at HEAD):
- `setMissionEnforcement(address)` onlyOwner
- `setMissionEnforcementEnabled(bool)` onlyOwner
- `setHumanTreasury(address payable)` onlyOwner
- `globalFlourishingScore(uint256)` view
- `inclusionMultiplier(uint256)` view
- `hasDecliningTrend(uint256)` view
- `timeMultiplier(uint256)` view
- `calculateBondValue(uint256)` view
- `calculateAppreciation(uint256)` view returns (int256)
- `verificationQualityScore(uint256)` view
- `shouldLockProfits(uint256)` view returns (bool, string)
- `getBond(uint256)` view returns (Bond)
- `getMetricsCount(uint256)` view / `getLatestMetrics(uint256)` view
- `getDistributionsCount(uint256)` / `getChallengesCount(uint256)` / `getAIVerificationsCount(uint256)` / `getLatestDistribution(uint256)` — all view
- Plus bond-lifecycle mutators inherited/embedded (source scan: full ABI export in PR3)

**`AIPartnershipBondsV2`** — public/external functions:
- `setMissionEnforcement(address)` / `setMissionEnforcementEnabled(bool)` onlyOwner
- `createBond(address aiAgent, string partnershipType)` payable whenNotPaused → bondId
- `requestDistribution(uint256)` onlyParticipants whenNotPaused
- `distributeBond(uint256)` nonReentrant whenNotPaused onlyParticipants
- All the same view helpers as accountability variant
- `getBondsByParticipant(address)` / `getBondsByParticipantCount(address)` — pagination-adjacent

### V2 events that MUST be preserved verbatim (any V3 changes go to new event names)

From `contracts-root/*V2.sol`:

- `event BondCreated(uint256 indexed bondId, address indexed human, address indexed aiAgent, string partnershipType, uint256 stakeAmount, uint256 timestamp)`
- `event BondCreated(uint256 indexed bondId, address indexed aiCompany, string companyName, uint256 quarterlyRevenue, uint256 stakeAmount, address stakeToken, uint256 timestamp)` (Accountability variant with different signature — indexer must switch on contract address, not just event name)
- `event BondDeactivated(uint256 indexed bondId, address indexed requester, uint256 timestamp)`
- `event BondDistributed(...)` — three signatures in codebase; indexer disambiguates by contract
- `event DistributionRequested(...)`
- `event MetricsChallenged(...)` / `event ChallengeResolved(...)`
- `event MetricsSubmitted(...)` / `event OracleMetricsConfirmed(...)`
- `event HumanVerificationSubmitted(...)` and `HumanVerificationSubmittedHashed(...)` variants
- `event AIVerificationSubmitted(...)`
- `event PartnershipFundAccrued(...)`, `PartnershipFundWithdrawn(...)`
- `event ContractPaused(address indexed by, uint256 timestamp)`, `ContractUnpaused(...)`
- `event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`
- Cross-chain: `event MessageSent(...)`, `MessageReceived(...)`, `AgentSynced(...)`, `PartnershipBondSynced(...)`, `AccountabilityBondSynced(...)`, `BondDeactivationSynced(...)`

**Full extracted event list:** 60+ event signatures across 21 core contracts. Extracted list saved to `baseline/extracted/v2_events.txt` in the PR1 exit commit.

**Rule:** V3 introduces new events under `V3` or explicit prefix (e.g. `BondCreatedV3`, `BondSettledV3`) — never reuse a V2 event name with different args.

---

## 3. API routes (all preserved; V3 adds parallel `/api/v3/*`)

Extracted from `repos/theloopbreaker-site/app/api/**/route.ts`: **123 route files**. Saved list at `baseline/extracted/v2_api_routes.txt`.

### Structural groups (all V2)

- **Contract discovery:** `/api/contracts`, `/api/abis`, `/api/abis/[name]`, `/api/openapi.json`, `/api/health`, `/api/live`
- **Hub read:** `/api/hub/stats`, `/api/hub/activity`, `/api/protocol/bond-counts`, `/api/protocol/distributions`, `/api/protocol/recent`
- **Agent read** (`/api/agent/*`): 33 routes — status, register, bond, discover, disputes, credentials, keys, tasks, etc.
- **x402 trust read** (`/api/x402/trust/*`): 25 routes — priced or free reads returning trust data (agent-status, agentproof-evidence, bonds, contracts, credentials, disputes, flourishing-metrics, health, insurance, leaderboard, protocol-stats, relationships, reputation-decay, risk-score, safety-status, scoped-delegations, sla-status, street-cred, vns-resolve, vouching, etc.)
- **x402 actions** (`/api/x402/actions/*`): 39 routes — priced state-changing operations (accept-bid, approve-work, attest-belief, batch-onboard, challenge-bond-metrics, create-accountability-bond, create-partnership-bond, create-task, dispute-task, file-attestation, mint-street-cred, register-agent, request-bond-distribution, revoke-consent, slash-reputation, submit-*-metrics, transfer-vns-name, etc.)
- **x402 infrastructure:** `/api/x402/settle`, `/api/x402/verify`, `/api/x402/submit-signed`, `/api/x402/cdp-register`, `/api/x402/contract-call`
- **Well-known:** `/.well-known/x402.json`, `/.well-known/agent-card.json`, `/api/.well-known/x402-email.json`
- **Admin:** `/api/admin/recent-payers`
- **Ops:** `/api/cron/heartbeat`, `/api/gifs`

### Compatibility rules

1. **No V2 route may be removed** during the pilot. Deprecated routes get `Deprecation:` and `Sunset:` headers per RFC 8594 with a minimum 90-day window.
2. **Only additive schema changes** on existing V2 responses. Every response gains these optional fields **only** (they do not break current consumers):
   - `protocolVersion` — string (`"v2"` or `"v3"`)
   - `contractStatus` — one of `active|legacy|deprecated|paused|read-only`
   - `blockNumber` / `blockHash`
   - `observedAt` (ISO-8601)
   - `finality` — `soft|safe|finalized`
   - `dataSourceErrors` — array (empty when healthy)
   - `schemaVersion` — semver
3. **V3 routes live at `/api/v3/*`** — parallel tree, never redirect writes from V2 to V3.
4. **Consumer-driven tests** — one snapshot fixture per response schema, checked in at `baseline/schemas/v2/*.json`, exercised in CI.

### Rule for RPC failures

Per assignment: "Never return a plausible zero/default when an RPC request failed." Any V2 route that currently returns `0` for balances, `[]` for arrays, or `null` for missing data when the RPC call itself failed must be patched to return `dataSourceErrors` populated and HTTP `503` with a machine-readable body. Audit needed in PR7.

---

## 4. SDK preservation

Published npm packages (per V3.3-R3 final audit and confirmed in `repos/`):

| Package | Repo path | Version at HEAD |
|---|---|---|
| `@vaultfire/agent-sdk` | `repos/vaultfire-sdk` | 0.7.1 |
| `@vaultfire/a2a` | published | 1.0.1 |
| `@vaultfire/langchain` | `repos/vaultfire-langchain` | 1.0.1 |
| `@vaultfire/vns` | published | 1.0.0 |
| `@vaultfire/x402` | `repos/vaultfire-x402` | 1.0.0 |
| `@vaultfire/xmtp` | `repos/vaultfire-xmtp` | 1.0.0 |
| `@vaultfire/contracts` | `repos/vaultfire-contracts-repo` | 1.0.0 |
| Chain-specific: `@vaultfire/polygon`, `@vaultfire/arbitrum` | | 1.0.0 |

### Public API surface (from `repos/vaultfire-sdk/src/index.ts`)

- `VaultfireSDK`, `createVaultfireSDK` — core client
- `VaultfireSafeSDK`, `createVaultfireSafeSDK`, `createVaultfireSafeSDKForChain` — privacy-preserving wrapper
- `BondsModule`, `BOND_CONTRACTS`
- `TrustModule` (partner-grade combined trust profile)
- `TasksModule`, `TASK_CONTRACTS`
- Types: `ChainId`, `VaultfireConfig`, `BeliefAttestation`, `VerificationResult`, `Attestation`, `ModuleInfo`, `BondType`, `PartnershipBond`, `AccountabilityBond`, `PartnershipBondParams`, `AccountabilityBondParams`, `InsuranceProfile`, `PoolStats`, `AgentTrustProfile`, `EscrowTask`, `TaskBid`, `CreateTaskParams`
- Enum: `ModuleType`

### Compatibility rules

1. **Every V2 method is preserved** as-is. No breaking type changes.
2. **V3 client is a separate module:** `VaultfireSDKv3` / `BondsModuleV3` / `MandateModuleV3` — importable side by side.
3. **Version-aware facade** reads both versions of a bond by inspecting `protocolVersion` in the response.
4. **Never silently redirect a write from V2 to V3.** Any method that mutates state must accept an explicit `version: "v2" | "v3"` argument for the pilot; default is `"v2"` until pilot gates pass.
5. Deprecation window: minimum 90 days between announcing a V2 SDK method deprecation and removing it, with a working V3 equivalent published first.

---

## 5. Indexer expectations

Assignment §Indexer requirements:
- Event identity: `(chainId, txHash, logIndex)` — must be the primary key.
- Handle reorgs, duplicate events, removed logs (`removed: true` on log objects), historical backfills, contract deprecations, multiple versions, partial RPC failure.

### Contracts the indexer must handle

For each of the 134 V2 instances plus every V3 contract that gets deployed, the indexer must:
1. Recognize by `(chainId, address)`.
2. Route V2 events to the V2 normalizer.
3. Route V3 events to the V3 normalizer.
4. Emit a normalized read model with `protocolVersion` and `contractStatus` fields.
5. On RPC 5xx or timeout, mark the affected range `stale` and refuse to serve zero-defaults.

### Handling contract-forked bytecode

Because 20 unique names have chain-specific bytecode forks, the indexer must load each `(chainId, address)` ABI independently. A single "one ABI per contract name" model is insufficient.

---

## 6. Website compatibility

Per assignment §Website:
- Existing V2 site remains functional through the pilot.
- V3 lives behind a feature flag (env `NEXT_PUBLIC_ENABLE_V3=true`).
- Labels required on every contract-touching UI:
  - `Legacy V2` — active but deprecated
  - `V3 test deployment` — testnet or unpaid pilot
  - `V3 audited pilot` — post-audit, capped pilot
  - `Deprecated` — read-only, no new writes
  - `Read-only` — historical only
- Users are never defaulted into V3 until all pilot gates pass (§Pilot gate in the assignment).

---

## 7. x402 registry (see `baseline/x402-route-registry.json` and `V2_X402_MATRIX.md`)

Live manifest at `https://theloopbreaker.com/.well-known/x402.json`: **88 endpoints** typed with method, path, price, asset, network, payee, x402 version.

Rule: `/.well-known/x402.json` in production must be generated from `baseline/x402-route-registry.json` in CI. No hand-written manifest. Every priced endpoint must be tested per assignment §x402 test list (correct 402 response, amount, asset, network, payee, signature validation, expiration, payment replay, request binding, double fulfillment, idempotency, settlement finality, facilitator timeout, HTTP-timeout-post-settle, receipt correctness).

---

## PR1 exit checklist for compatibility

- [x] `deployments.json` is single source of truth
- [x] All 134 instances inventoried by (chain, name, address, bytecodeSha256, hasCode, nativeBalance, owner, isProxy)
- [x] V3.3-R3 audit findings integrated into P0/P1 finding list
- [x] Access-control matrix reflects verified on-chain reality (16-contract selector-scan)
- [ ] `contractStatus` field added to every entry in `deployments.json` (pending)
- [ ] `baseline/extracted/v2_events.txt` full export (pending — extraction of every event across all 4,348 files)
- [ ] `baseline/schemas/v2/*.json` response-schema snapshots for the 123 API routes (pending — pass done in PR7)
- [ ] V3 events named to never collide with V2 (design rule — enforced in PR2 spec)
