harb/VERSION_VALIDATION.md
openhands de3c8eef94 docs: consolidate and update all documentation for launch readiness
- Rewrite root README.md with proper project overview, tech stack, and repo structure
- Remove duplicate CLAUDE.md files (root, onchain, ponder) — AGENTS.md is the standard
- Update HARBERG.md to reflect Stage 1 completion and Stage 2 evolution
- Delete stale onchain/testing_todos.md (all high-priority items completed)
- Update VERSION_VALIDATION.md for VERSION=2
- Trim root AGENTS.md: replace Docker duplication with docs/docker.md reference
- Trim onchain/AGENTS.md (129→71 lines): reference TECHNICAL_APPENDIX for formulas
- Trim web-app/AGENTS.md (278→55 lines): remove internal API docs, keep architecture
- Rewrite onchain/README.md: add contract table, deployment addresses, analysis links
- Trim services/ponder/README.md: remove stale subgraph comparison
- Add otterscan to docs/docker.md service topology
- Update TECHNICAL_APPENDIX.md references

Net: -388 lines across documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:22:34 +00:00

8.4 KiB

Version Validation System

Overview

The Kraiken protocol now includes a version validation system that ensures all stack components (contract, indexer, frontend) are synchronized and compatible. This prevents subtle data corruption bugs that arise from version mismatches.

Architecture

┌─────────────────────────────────────┐
│  Kraiken.sol                        │
│  uint256 public constant VERSION=2  │  ← Source of Truth
└──────────────┬──────────────────────┘
               │ read at startup
               ▼
┌─────────────────────────────────────┐
│  Ponder Indexer                     │
│  • Reads contract.VERSION()         │
│  • Validates against                │
│    COMPATIBLE_CONTRACT_VERSIONS     │
│  • FAILS HARD if mismatch           │
└──────────────┬──────────────────────┘
               │ GraphQL
               ▼
┌─────────────────────────────────────┐
│  Frontend (web-app)                 │
│  • Checks KRAIKEN_LIB_VERSION       │
│  • Shows warning if issues          │
│  • Continues operation              │
└─────────────────────────────────────┘

Components

1. Contract Version Constant

File: onchain/src/Kraiken.sol

contract Kraiken is ERC20, ERC20Permit {
    /**
     * @notice Protocol version for data structure compatibility.
     * Increment when making breaking changes to TAX_RATES, events, or core data structures.
     */
    uint256 public constant VERSION = 2;

    // ...
}

Key properties:

  • public constant = free to read, immutable
  • Forces contract redeployment on breaking changes
  • Single source of truth for the entire stack

2. kraiken-lib Version Tracking

File: kraiken-lib/src/version.ts

export const KRAIKEN_LIB_VERSION = 2;

export const COMPATIBLE_CONTRACT_VERSIONS = [1, 2];

export function isCompatibleVersion(contractVersion: number): boolean {
  return COMPATIBLE_CONTRACT_VERSIONS.includes(contractVersion);
}

Key features:

  • Manually maintained list (not parsed from contract)
  • Allows backward compatibility (lib can support multiple contract versions)
  • Exported by kraiken-lib/src/index.ts for all consumers

3. Ponder Validation (FAIL HARD)

File: services/ponder/src/helpers/version.ts

export async function validateContractVersion(context: Context): Promise<void> {
  const contractVersion = await context.client.readContract({
    address: context.contracts.Kraiken.address,
    abi: context.contracts.Kraiken.abi,
    functionName: 'VERSION',
  });

  if (!isCompatibleVersion(Number(contractVersion))) {
    console.error(getVersionMismatchError(contractVersion, 'ponder'));
    process.exit(1);  // FAIL HARD
  }
}

Called in: services/ponder/src/kraiken.ts (first Transfer event)

Behavior:

  • Reads VERSION from deployed Kraiken contract
  • Compares against COMPATIBLE_CONTRACT_VERSIONS
  • Exits with error if incompatible (prevents indexing wrong data)
  • Logs success if compatible

4. Frontend Validation (WARN)

File: web-app/src/composables/useVersionCheck.ts

export function useVersionCheck() {
  async function checkVersions(graphqlUrl: string) {
    // Currently placeholder - validates lib loaded correctly
    // Future: Query Ponder for stored contract version
    versionStatus.value = {
      isValid: true,
      libVersion: KRAIKEN_LIB_VERSION,
    };
  }
  // ...
}

Behavior:

  • Validates KRAIKEN_LIB_VERSION is loaded
  • Future enhancement: Query Ponder GraphQL for contract version
  • Shows warning banner if mismatch (doesn't break app)

5. CI/CD Validation

File: .woodpecker/release.yml (version-check step)

The Woodpecker release pipeline validates version consistency on tagged releases. The version-check step:

  1. Builds kraiken-lib (including sync-tax-rates.mjs)
  2. Runs an inline Node.js script that:
    • Extracts VERSION from Kraiken.sol
    • Extracts KRAIKEN_LIB_VERSION and COMPATIBLE_CONTRACT_VERSIONS from kraiken-lib/src/version.ts
    • Fails if contract VERSION differs from lib VERSION
    • Fails if contract VERSION is not in COMPATIBLE_CONTRACT_VERSIONS

Triggered on: tag events (releases)

Prevents:

  • Releasing with incompatible versions
  • Deploying with stale kraiken-lib

Workflows

Version Bump (Breaking Change)

When modifying TAX_RATES or other critical data structures:

1. Edit onchain/src/Kraiken.sol
   uint256 public constant VERSION = 2;  // Increment

2. Edit kraiken-lib/src/version.ts
   export const KRAIKEN_LIB_VERSION = 2;
   export const COMPATIBLE_CONTRACT_VERSIONS = [2];  // Or [1, 2] for backward compat

3. Rebuild kraiken-lib
   ./scripts/build-kraiken-lib.sh

4. Clear Ponder state
   rm -rf services/ponder/.ponder/

5. Redeploy contracts (if needed)
   cd onchain && forge script ...

6. Restart stack
   ./scripts/dev.sh restart --full

Adding Backward Compatibility

If lib can work with old AND new contract versions:

// kraiken-lib/src/version.ts
export const KRAIKEN_LIB_VERSION = 2;
export const COMPATIBLE_CONTRACT_VERSIONS = [1, 2];  // Supports both

Ponder will accept either v1 or v2 contracts.

Troubleshooting

Ponder fails with "VERSION MISMATCH"

╔════════════════════════════════════════════════════════════╗
║  ❌ CRITICAL: VERSION MISMATCH (ponder)                     
╠════════════════════════════════════════════════════════════╣
║  Contract VERSION:      2
║  Library VERSION:       1
║  Compatible versions:   1

Fix:

  1. Check if contract was upgraded
  2. Update COMPATIBLE_CONTRACT_VERSIONS in kraiken-lib/src/version.ts
  3. Run ./scripts/build-kraiken-lib.sh
  4. Run rm -rf services/ponder/.ponder/
  5. Restart Ponder

CI/CD check fails

❌ Contract VERSION (2) not in COMPATIBLE_CONTRACT_VERSIONS

Fix:

  • Update kraiken-lib/src/version.ts to include new version
  • Or revert contract changes if unintentional

Benefits

Prevents data corruption - Ponder won't index with wrong schema
Early detection - Fails at startup, not after hours of indexing
Clear errors - Tells you exactly what to do
Backward compat - Can support multiple versions if needed
CI enforcement - Prevents merging incompatible changes
Future-proof - Easy to extend to other contracts (Stake, LiquidityManager)

Future Enhancements

  1. Store version in Ponder stats table

    • Add contractVersion column to stats
    • Frontend can query via GraphQL
    • Enables full 3-way validation (contract → Ponder → frontend)
  2. Multi-contract versioning

    • Add VERSION to Stake.sol, LiquidityManager.sol
    • Track all contract versions in kraiken-lib
    • Validate full deployment is compatible
  3. Version migration helpers

    • Scripts to handle data migrations
    • Backward-compatible event handling
    • Gradual rollout support

Maintenance

When to increment VERSION

Increment when changes affect indexed data or frontend interpretation:

  • Modifying TAX_RATES array
  • Adding/removing event parameters
  • Changing event names
  • Modifying struct definitions that frontends consume
  • Breaking changes to staking logic

Don't increment for:

  • Gas optimizations (no data changes)
  • Internal logic changes (if events unchanged)
  • Comment updates
  • Pure view function changes

Documentation

Update VERSION comment in contract with each change:

/**
 * Version History:
 * - v1: Initial deployment (30-tier TAX_RATES)
 * - v2: Added new tax tier at 150% (31 tiers total)
 * - v3: Modified PositionCreated event (added taxRateIndex field)
 */
uint256 public constant VERSION = 3;

This creates an audit trail for version changes.