- 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>
271 lines
8.4 KiB
Markdown
271 lines
8.4 KiB
Markdown
# 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`
|
|
|
|
```solidity
|
|
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`
|
|
|
|
```typescript
|
|
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`
|
|
|
|
```typescript
|
|
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`
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```typescript
|
|
// 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:
|
|
|
|
```solidity
|
|
/**
|
|
* 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.
|