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>
This commit is contained in:
openhands 2026-02-13 19:22:34 +00:00
parent b7260b2eaf
commit de3c8eef94
14 changed files with 249 additions and 701 deletions

View file

@ -53,35 +53,19 @@ Docker Engine (Linux) or Colima (Mac). See `docs/docker.md` for installation.
- **E2E Tests**: Playwright-based full-stack tests in `tests/e2e/` verify complete user journeys (mint ETH → swap KRK → stake). Run with `npm run test:e2e` from repo root. Tests use mocked wallet provider with Anvil accounts. In CI, the Woodpecker e2e pipeline runs these against pre-built service images.
## Version Validation System
- **Contract VERSION**: `Kraiken.sol` exposes a `VERSION` constant (currently v1) that must be incremented for breaking changes to TAX_RATES, events, or core data structures.
- **Contract VERSION**: `Kraiken.sol` exposes a `VERSION` constant (currently v2) that must be incremented for breaking changes to TAX_RATES, events, or core data structures.
- **Ponder Validation**: On startup, Ponder reads the contract VERSION and validates against `COMPATIBLE_CONTRACT_VERSIONS` in `kraiken-lib/src/version.ts`. Fails hard (exit 1) on mismatch to prevent indexing wrong data.
- **Frontend Check**: Web-app validates `KRAIKEN_LIB_VERSION` at runtime (currently placeholder; future: query Ponder GraphQL for full 3-way validation).
- **CI Enforcement**: Woodpecker `release.yml` pipeline validates that contract VERSION matches `COMPATIBLE_CONTRACT_VERSIONS` before release.
- See `VERSION_VALIDATION.md` for complete architecture, workflows, and troubleshooting.
## Docker Installation & Setup
- **Linux**: Install Docker Engine via package manager or `curl -fsSL https://get.docker.com | sh`, then add user to docker group: `sudo usermod -aG docker $USER` (logout/login required)
- **Mac**: Use Colima (open-source Docker Desktop alternative):
```bash
brew install colima docker docker-compose
colima start --cpu 4 --memory 8 --disk 100
docker ps # verify installation
```
- **Container Orchestration**: `docker-compose.yml` has NO `depends_on` declarations. All service ordering is handled in `scripts/dev.sh` via phased startup with explicit health checks.
- **Startup Phases**: (1) Start anvil+postgres and wait for healthy, (2) Start bootstrap and wait for exit, (3) Start ponder and wait for healthy, (4) Start webapp/landing/txn-bot, (5) Start caddy, (6) Smoke test via `scripts/wait-for-service.sh`.
- **Shared Bootstrap**: Contract deployment, seeding, and funding logic lives in `scripts/bootstrap-common.sh`, sourced by both `containers/bootstrap.sh` (local dev) and `scripts/ci-bootstrap.sh` (CI). Constants (FEE_DEST, WETH, SWAP_ROUTER, default keys) are defined once there.
- **Logging Configuration**: All services have log rotation configured (max 10MB per file, 3 files max = 30MB per container) to prevent disk bloat. Logs are automatically rotated by Docker.
- **Disk Management** (Portable, No Per-Machine Setup Required):
- **20GB Hard Limit**: The stack enforces a 20GB total Docker disk usage limit (images + containers + volumes + build cache).
- **Pre-flight Checks**: `./scripts/dev.sh start` checks Docker disk usage before starting and refuses to start if over 20GB.
- **Aggressive Auto-Cleanup on Stop**: `./scripts/dev.sh stop` automatically prunes ALL unused Docker resources including build cache (the primary cause of bloat).
- **Named Volumes for node_modules**: All Node.js services (ponder, webapp, landing, txnBot) use named Docker volumes for `node_modules/` instead of writing to the host filesystem. This prevents host pollution (20-30GB savings) and ensures `docker system prune --volumes` cleans them up.
- **npm Best Practices**: All entrypoints use `npm ci` (not `npm install`) for reproducible builds and `npm cache clean --force` to remove ~50-100MB of cache per service.
- **PostgreSQL WAL Limits**: Postgres configured with `wal_level=minimal`, `max_wal_size=128MB`, and `archive_mode=off` to prevent unbounded WAL file growth in the postgres volume.
- **Log Rotation**: All containers limited to 30MB logs (10MB × 3 files) via docker-compose logging configuration.
- **.dockerignore**: Excludes `node_modules/`, caches, and build outputs from Docker build context to speed up builds and reduce image size.
- **Monitoring**: The stack displays current Docker disk usage on startup and warns at 80% (16GB).
- **Note**: Docker has no built-in portable disk quotas. All limits are enforced via aggressive pruning, bounded configurations, and isolation of dependencies to Docker volumes.
## Docker
See `docs/docker.md` for Docker/Colima installation and the full service topology. Key facts:
- `docker-compose.yml` has NO `depends_on`. Service ordering is handled by `scripts/dev.sh`.
- Startup phases: anvil+postgres → bootstrap → ponder → webapp/landing/txn-bot → caddy → smoke test.
- Shared bootstrap: `scripts/bootstrap-common.sh` (sourced by both local dev and CI).
- 20GB disk limit enforced. `dev.sh stop` auto-prunes. Named volumes for `node_modules`.
- All services have log rotation (30MB max per container) and PostgreSQL WAL limits configured.
## Guardrails & Tips
- `token0isWeth` flips amount semantics; confirm ordering before seeding or interpreting liquidity.

View file

@ -1 +0,0 @@
AGENTS.md

View file

@ -1,27 +1,16 @@
# Harberg
# Harberger (Stage 1)
## product
A staking market balanced by the Harberger Tax.
The foundation layer of the KRAIKEN protocol. A staking market balanced by the Harberger tax.
## token
$HRB is created when users buy more tokens and sell less from the uniswap pool (mainly from the liquidity position owned by the Harberg protocol)
## Status: Complete
## staking
users can stake tokens - up to 20% of the total supply. When supply increases (more people buy then sell) stakers will keep the total supply they staked. So 1% of staked total supply remains 1%.
Stage 1 established the core mechanisms now used by Stage 2 (KRAIKEN):
- **Token**: KRAIKEN (KRK) — minted on buys from the LiquidityManager's Uniswap V3 positions, burned on sells
- **Staking**: Users stake tokens and declare a self-assessed tax rate. Stakers maintain percentage ownership of total supply as it grows.
- **Snatching**: Any position can be taken by someone willing to pay a higher tax rate, creating a competitive prediction market for token value
- **Tax collection**: Automated by the transaction bot (`services/txnBot/`)
## landing
in the landing folder in this repository you find the front-end implementation.
## Evolution
## contracts
in the onchain folder are the smart contracts implementing the token and the economy
## services
1 bot collecting taxes on old stakes and liquidate stakers if tax is not paid
1 bot calling recenter on the liquidity provider contract
## subgraph
- data backend for front-end for landing project
## hosting
- crypto friendly
Stage 1's static liquidity strategy evolved into Stage 2's three-position dynamic strategy with OptimizerV3. The Harberger staking mechanism now serves as the sentiment oracle driving optimizer parameter selection. See [TECHNICAL_APPENDIX.md](TECHNICAL_APPENDIX.md) for details.

124
README.md
View file

@ -1,39 +1,113 @@
$HRB is a gig to become successful in DeFi. It is a protocol that implements the fairest ponzi in the world.
# KRAIKEN
This repository structures our approach and manages our collaboration to achieve this goal.
The fairest ponzi in the world.
KRAIKEN is a DeFi protocol that couples Harberger-tax staking with a dominant Uniswap V3 liquidity manager. The result: asymmetric slippage, sentiment-driven pricing, and VWAP-based price memory that protects the protocol from exploitation.
## Project Milestones
Deployed on [Base](https://base.org).
The fairest ponzi in the world will be launched in 3 stages, each representing a more advanced version of the previous one.
## The Three Stages
1. [Harberg](HARBERG.md) - a staking market and an speculative laverage platform.
2. KrAIken - Harberg, but token issuance is governed by an automated liquidity manager.
3. SoverAIgns - KrAIKen, but the liquidity manager is augmented by AI and deliveres outlandish performance
1. **Harberger** — A staking market balanced by the Harberger tax. *Complete.*
2. **KRAIKEN** — Token issuance governed by an automated liquidity manager. *Current stage.*
3. **SoverAIgns** — The liquidity manager augmented by AI for outlandish performance. *Future.*
## How It Works
## Project Values and Organization
- the core value and mantra of the project is: **ship, ship,** :ship:
- delivery is valued highest and goes over quality or communication
- if you see work, do it. most likely every-one but you will lose interest in the project, and you will deliver it by yourself. work this way, take responsibility for everything. document everything methodically in this repository, use .md files, commits, issues(feature request, support issue), and pull requests. if other people still follow this repository collaboration will emerge, and duplication of work will be avoided automatically.
- **no structured communication outside of this repository** is relevant for the success, nor will it be rewarded.
### Three-Position Liquidity Strategy
### open questions
- multisig? keyholders?
- payout, shares?
The LiquidityManager maintains three Uniswap V3 positions simultaneously:
## Revenue Sources
- the tax paid by the stakers will be forwarded to the multisig
- the liquidity manager contract will collect all liquidity fees and forward them to the multisig
- at launch of each stage of the project the keyholders will invest a share of the [multisig]() holdings and coordinate to sell at a favorable time. all profits from all sales are the multisigs profits.
- **Anchor** — Shallow liquidity near the current price. Fast price discovery, high slippage for attackers.
- **Discovery** — Medium liquidity bordering the anchor. The fee capture zone.
- **Floor** — Deep liquidity at VWAP-adjusted distance. Price memory that protects against whale dumps.
## Timeline
it would be great if we can launch stage 1 or even 2 for DevCon.
Any round-trip trade (buy → recenter → sell) pays disproportionate slippage costs twice, making manipulation unprofitable.
### Harberger Tax Sentiment Oracle
## Kick-off Call Harberg
Agenda
Stakers self-assess tax rates on their positions. Higher tax = higher confidence. Positions can be snatched by anyone willing to pay more. This creates a continuous prediction market for token sentiment.
### OptimizerV3
- [design doc](https://hackmd.io/JvxEI0fnR_uZsIrrBm95Qw)
- [Liquidity Provisioning in KRAIKEN](https://hackmd.io/yNiN3TyETT2A1uwQVGYiSA)
Reads staking data (% staked, average tax rate) and outputs a binary bear/bull configuration:
- **Bear** (~94% of state space): AS=30%, AW=100, CI=0, DD=0.3e18 — protective
- **Bull** (>91% staked, low tax): AS=100%, AW=20, CI=0, DD=1e18 — aggressive fee capture
The binary step avoids the AW 40-80 kill zone where intermediate parameters are exploitable.
### VWAP Floor Defense
The floor position uses volume-weighted average price with directional recording (buys only). During sell pressure, the VWAP-to-price distance grows, making the floor resist walkdown. This gives the protocol "eternal memory" against dormant whale attacks.
## Tech Stack
| Component | Technology | Location |
|-----------|-----------|----------|
| Smart Contracts | Solidity, Foundry | `onchain/` |
| Indexer | Ponder (TypeScript) | `services/ponder/` |
| Staking App | Vue 3, Vite, Wagmi | `web-app/` |
| Landing Page | Vue 3, Vite | `landing/` |
| Automation Bot | Node.js, Express | `services/txnBot/` |
| Shared Library | TypeScript | `kraiken-lib/` |
| Block Explorer | Otterscan | Docker service |
| Reverse Proxy | Caddy | Docker service |
## Repository Structure
```
harb/
├── onchain/ # Solidity contracts, tests, deployment scripts, analysis
│ ├── src/ # Core: Kraiken, Stake, LiquidityManager, OptimizerV3
│ ├── test/ # Foundry test suite
│ ├── script/ # Deployment scripts
│ └── analysis/ # Fuzzing, parameter sweeps, security review
├── services/
│ ├── ponder/ # Blockchain indexer → GraphQL API
│ └── txnBot/ # recenter() + payTax() automation
├── web-app/ # Staking dashboard (Vue 3)
├── landing/ # Marketing site (Vue 3)
├── kraiken-lib/ # Shared TypeScript helpers and ABIs
├── tests/e2e/ # Playwright end-to-end tests
├── scripts/ # Dev environment, CI bootstrap, utilities
├── docker/ # CI Dockerfiles
├── containers/ # Entrypoints, Caddyfile
└── docs/ # Deployment runbook, Docker guide
```
## Quick Start
```bash
# Prerequisites: Docker Engine (Linux) or Colima (Mac)
# See docs/docker.md for installation
nohup ./scripts/dev.sh start & # Start full stack (~3-6 min first time)
tail -f nohup.out # Watch progress
./scripts/dev.sh health # Verify all services healthy
```
Access points (via Caddy on port 8081):
- Landing: http://localhost:8081/
- Staking app: http://localhost:8081/app/
- GraphQL: http://localhost:8081/api/graphql
## Contracts (Base Mainnet)
| Contract | Address |
|----------|---------|
| Kraiken | `0x45caa5929f6ee038039984205bdecf968b954820` |
| Stake | `0xed70707fab05d973ad41eae8d17e2bcd36192cfc` |
| LiquidityManager | `0x7fd4e645ce258dd3942eddbeb2f99137da8ba13b` |
## Documentation
- [AGENTS.md](AGENTS.md) — Development guide and operational reference
- [TECHNICAL_APPENDIX.md](TECHNICAL_APPENDIX.md) — Deep technical analysis of protocol mechanics
- [docs/DEPLOYMENT_RUNBOOK.md](docs/DEPLOYMENT_RUNBOOK.md) — Production deployment guide
- [onchain/UNISWAP_V3_MATH.md](onchain/UNISWAP_V3_MATH.md) — Uniswap V3 math reference
- [onchain/analysis/SECURITY_REVIEW.md](onchain/analysis/SECURITY_REVIEW.md) — Security analysis and fuzzing results
## License
GPL-3.0-or-later

View file

@ -1,6 +1,6 @@
# Technical Appendix
This document provides detailed technical analysis and implementation details for the KRAIKEN protocol's core innovations. For a high-level overview, see AGENTS.md.
This document provides detailed technical analysis and implementation details for the KRAIKEN protocol's core innovations. For a high-level overview, see [README.md](README.md).
## Asymmetric Slippage Strategy
@ -152,5 +152,6 @@ The binary step avoids the AW 40-80 kill zone where intermediate parameters are
- **Scenario Visualization**: Tools for understanding liquidity dynamics
### Related Documentation
- **AGENTS.md**: High-level overview and development guidance
- **README.md**: Project overview
- **AGENTS.md**: Development and operational guidance
- **`/onchain/analysis/README.md`**: Detailed analysis tool usage

View file

@ -9,7 +9,7 @@ The Kraiken protocol now includes a **version validation system** that ensures a
```
┌─────────────────────────────────────┐
│ Kraiken.sol │
│ uint256 public constant VERSION=1 │ ← Source of Truth
│ uint256 public constant VERSION=2 │ ← Source of Truth
└──────────────┬──────────────────────┘
│ read at startup
@ -42,8 +42,8 @@ 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 = 1;
uint256 public constant VERSION = 2;
// ...
}
```
@ -58,9 +58,9 @@ contract Kraiken is ERC20, ERC20Permit {
**File:** `kraiken-lib/src/version.ts`
```typescript
export const KRAIKEN_LIB_VERSION = 1;
export const KRAIKEN_LIB_VERSION = 2;
export const COMPATIBLE_CONTRACT_VERSIONS = [1];
export const COMPATIBLE_CONTRACT_VERSIONS = [1, 2];
export function isCompatibleVersion(contractVersion: number): boolean {
return COMPATIBLE_CONTRACT_VERSIONS.includes(contractVersion);

View file

@ -10,6 +10,7 @@ The Docker stack powers `scripts/dev.sh` using containerized services. Every boo
- `webapp` Vite dev server for `web-app` (port 5173)
- `landing` Vite dev server for landing page (port 5174)
- `txn-bot` automation loop plus Express status API (port 43069)
- `otterscan` block explorer UI (port 5100)
- `caddy` reverse proxy at `http://localhost:8081`, routing `/app/` → webapp, `/api/graphql` → ponder, `/api/rpc` → anvil, `/` → landing
All containers mount the repository so code edits hot-reload exactly as the local script. Named volumes keep `node_modules` caches between restarts.

View file

@ -8,122 +8,63 @@
- Every swap through the LM's positions generates Uniswap LP fees
- Fees (WETH + KRK) flow to `feeDestination` — this is what founders withdraw
- Locked ETH in the protocol has NO value to founders — it's locked forever
- More trading volume = more fees = more revenue
- The protocol WANTS active trading, even if traders extract some ETH
**Bull market behavior (desired):**
- Encourage risk-taking: wide anchor, big discovery → catch more trades, earn more fees
- Floor can be minimal — ETH abundance means low risk
- Parameters should maximize fee capture, not protect locked ETH
**Bear market behavior (desired):**
- Protect the floor: prevent catastrophic ETH drain
- But NOT at the expense of killing all trading — some exposure is acceptable
- The question is always: does protecting X ETH cost more in lost fees than it saves?
**The optimization target is NOT "minimize trader PnL". It is "maximize fee revenue while keeping the protocol solvent."** Trader losses beyond what's needed for solvency represent missed fee opportunities.
**Key mechanism: Floor placement**
The floor position protects protocol solvency by holding ETH far from the current price. Its tick is computed as:
```
floorTick = max(scarcityTick, mirrorTick, clampTick) toward KRK-cheap side
```
Three signals determine the floor:
- **scarcityTick**: derived from `vwapX96` and ETH/supply ratio. Correct when ETH is scarce.
- **mirrorTick**: `currentTick + |adjustedVwapTick - currentTick|` on KRK-cheap side. Reflects VWAP distance symmetrically. Uses `getAdjustedVWAP(CI)`.
- **clampTick**: minimum distance from anchor edge. `anchorSpacing = 200 + (34 × 20 × AW / 100)` ticks.
There is no EthScarcity/EthAbundance branching — the unified formula takes the max of all three signals.
**VWAP mirror defense:** During sell-heavy trading, the current tick drops but the VWAP stays higher, so the mirror distance *grows* — the floor naturally resists being walked down. CI controls mirror distance through `getAdjustedVWAP(CI)` with no magic numbers.
**Directional VWAP recording:** VWAP only records on ETH inflow (buys into the LM), preventing attackers from diluting VWAP with sells. `shouldRecordVWAP` compares `lastRecenterTick` to current tick to detect direction. Bootstrap: always records when `cumulativeVolume == 0`. (Commits `c97714c` + `ba018c4`.)
**The optimization target is NOT "minimize trader PnL". It is "maximize fee revenue while keeping the protocol solvent."**
**Four optimizer parameters:**
- `capitalInefficiency (CI)` — adjusts VWAP for floor placement: adjustedVWAP = 70%*VWAP + CI*VWAP. **Zero effect on fee revenue** — pure risk lever. CI=0% is safest.
- `anchorShare (AS)` — ETH split between floor and anchor (low AS = more floor, high AS = more anchor)
- `anchorWidth (AW)`how wide the anchor position is in ticks
- `capitalInefficiency (CI)` — adjusts VWAP for floor placement. **Zero effect on fee revenue** — pure risk lever. CI=0% is safest.
- `anchorShare (AS)` — ETH split between floor and anchor
- `anchorWidth (AW)` — anchor position width in ticks
- `discoveryDepth (DD)` — discovery position liquidity density. **Zero effect on floor safety.**
**Parameter safety (2D frontier):**
See [TECHNICAL_APPENDIX.md](../TECHNICAL_APPENDIX.md) for floor placement formula, parameter safety frontier, and asymmetric slippage analysis.
Only extreme AS×AW configurations survive adversarial attack:
## OptimizerV3
| Config | Safe | Why |
|--------|------|-----|
| AS ≤ 35%, AW = 100 | Yes | Wide clamp (7000 ticks) prevents floor drain. Thin anchor = less ETH for attacker. |
| AS ≥ 50%, AW = 20 | Yes | Thin concentrated anchor near price. Floor far away with minimal ETH. |
| AW 40-80 at most AS | **No** | Kill zone — moderate depth AND moderate clamp distance. |
`src/OptimizerV3.sol` — UUPS upgradeable. Binary bear/bull from staking sentiment.
**Design principle: Fix root causes, don't add band-aids.** Safety comes from the parameter space, not from position ratchets or overrides.
**Inputs:** `percentageStaked` (0-100%), `averageTaxRate` (effective index 0-29)
## Optimizer V3
**Mapping:**
- `staked <= 91%` → always **BEAR**: AS=30%, AW=100, CI=0, DD=0.3e18
- `staked > 91%`**BULL** if `deltaS^3 * effIdx / 20 < 50`: AS=100%, AW=20, CI=0, DD=1e18
`src/OptimizerV3.sol` — UUPS upgradeable. Uses on-chain Harberger staking data to switch between safe bear and aggressive bull configurations.
The binary step avoids the AW 40-80 kill zone. ~94% of state space maps to bear.
**Inputs:** `percentageStaked` (0-100%), `averageTaxRate` (maps to effective index 0-29 in discrete tax array, with +1 shift at index ≥14)
## Staking Triangle Cycle
**Direct 2D mapping — no intermediate score:**
- `staked ≤ 91%` → always **BEAR** (no euphoria signal)
- `staked > 91%`**BULL** if `deltaS³ × effIdx / 20 < 50`, else BEAR
- `deltaS = 100 - stakedPct` (0-8 range)
- Bull requires high staking AND low tax. Any decline snaps to bear instantly.
**Binary parameter output:**
- **BEAR**: AS=30%, AW=100, CI=0, DD=0.3e18
- **BULL**: AS=100%, AW=20, CI=0, DD=1e18
The binary step avoids the AW 40-80 kill zone entirely. ~94% of the staking state space maps to bear.
## Harberger Staking Triangle Cycle
The staking system naturally traces a triangle in (staking%, avgTax) space:
**Phase 1 — Fill up (bottom edge):** Staking grows 0→100%, tax starts low. Optimizer stays bear. Transitions to bull at ~95% staked.
**Phase 2 — Snatching wars (right edge):** 100% staked, snatching wars push average tax rate up. Always bull. Euphoria overwhelms tax cost.
**Phase 3 — Collapse (hypotenuse):** Nervous exits. High tax + declining staking → cubic term snaps to bear within 4-6% staking drop.
Game theory validates this trajectory — incentive structures force participants through this cycle.
The staking system traces a triangle in (staking%, avgTax) space:
1. **Fill up:** Staking grows 0→100%, tax low. Optimizer stays bear. Bull at ~95%.
2. **Snatching wars:** 100% staked, tax rises. Always bull.
3. **Collapse:** Nervous exits. Cubic term snaps to bear within 4-6% staking drop.
## System Snapshot
- Solidity/Foundry DeFi protocol built around the Kraiken ERC20 token, a staking auction, and a three-position Uniswap V3 liquidity manager.
- LiquidityManager.sol mints/burns supply to maintain ANCHOR (near price), DISCOVERY (offset discovery band), and FLOOR (VWAP-protected) positions with asymmetric slippage to resist arbitrage.
- VWAPTracker.sol stores squared price in X96 format, compresses history, and feeds adjusted VWAP data for FLOOR placement. VWAP records directionally (ETH inflow only).
- OptimizerV3.sol (UUPS upgradeable) reads staking sentiment to output capitalInefficiency, anchorShare, anchorWidth, and discoveryDepth via a direct 2D binary mapping.
- Stake.sol runs the self-assessed tax staking system with snatching auctions, discrete tax brackets, and redistribution to tax recipients/UBI.
- Kraiken ERC20 with mint/burn via LiquidityManager. VERSION=2.
- LiquidityManager.sol: ANCHOR + DISCOVERY + FLOOR positions with asymmetric slippage.
- VWAPTracker.sol: squared price in X96, compression, directional recording (ETH inflow only).
- OptimizerV3.sol: UUPS upgradeable, direct 2D binary mapping.
- Stake.sol: self-assessed tax, snatching auctions, discrete brackets, UBI redistribution.
## Development Workflow
- Tooling: Foundry (`forge build`, `forge test`, `forge fmt`, `forge snapshot`), Anvil for local chain, Base Sepolia deployment script (`forge script ...BaseSepoliaDeploy`).
- Repo structure highlights: `src/` (core contracts), `test/helpers/` (Uniswap/Kraiken bases), `lib/uni-v3-lib` (math + JS setup), `script/` (deploy), `out/` (artifacts), config via `foundry.toml` & `remappings.txt`.
- Setup steps: clone repo, init/update submodules (`git submodule update --init --recursive`), install `lib/uni-v3-lib` dependencies (`npm install` in `lib/uni-v3-lib/`), ensure Foundry installed.
- **ABI Architecture**: Contract ABIs are exported via `kraiken-lib/src/abis.ts`, which imports directly from `onchain/out/` (forge build artifacts). All consumers (ponder, web-app) import from kraiken-lib for type-safe, single-source-of-truth ABIs. Run `forge build` in `onchain/` to update ABIs across the stack.
- Foundry: `forge build`, `forge test`, `forge fmt`, `forge snapshot`.
- Repo: `src/` (contracts), `test/helpers/` (Uniswap/Kraiken bases), `lib/uni-v3-lib` (math), `script/` (deploy).
- Setup: `git submodule update --init --recursive`, `npm install` in `lib/uni-v3-lib/`, Foundry installed.
- **ABI flow**: `kraiken-lib/src/abis.ts` imports from `onchain/out/`. Run `forge build` to update ABIs stack-wide.
## Containerized Builds (Podman/Docker)
- **Git Submodules**: Must be initialized before building (`git submodule update --init --recursive`). Empty `lib/` directories cause compilation failures.
- **uni-v3-lib Dependencies**: Requires `npm install` in `lib/uni-v3-lib/` to populate `node_modules/` with Uniswap interfaces (IUniswapV3Pool, IUniswapV3Factory) and solady dependencies.
- **Foundry Image**: Use `ghcr.io/foundry-rs/foundry:latest` for containers. The image includes `forge`, `cast`, `anvil` but NOT `jq` or `curl`.
- **Root Access**: Bootstrap scripts that create deployment artifacts may need to run as root (user: "0:0") to write to mounted volumes.
- **Volume Permissions**: Use `:z` (shared SELinux label) instead of `:Z` (private) for multi-container access to the same mount.
## Testing & Analysis
- Fuzzing under `analysis/`: configurable trade/stake biases, adversarial attacks, parameter sweeps. See `analysis/README.md`.
- Adversarial testing (`run-adversarial.sh`, `run-v3-adversarial.sh`) validates floor defense.
- Background LP analysis (`run-bglp-fee-test.sh`) measures fee retention under LP competition.
## Strategy & Mechanics
- Outstanding supply excludes liquidity position balances and KRK held by `feeDestination`/`stakingPool`; enforce 20% staking cap (~20k positions).
- Anchor width and discovery depth adjusted dynamically; anchorShare tunes ETH allocation, discoveryDepth controls liquidity density multiples, capitalInefficiency shifts VWAP floor valuation (70%-170%).
- `token0isWeth` flag flips meaning of amount0/amount1 to ETH/KRAIKEN respectively.
- Recenter logic keeps Uniswap positions aligned; floor placement uses `vwapX96` directly (not sqrt) in fixed-point math.
## Containerized Builds
- Git submodules must be initialized before building.
- `lib/uni-v3-lib/` needs `npm install` for Uniswap interfaces.
- Foundry image: `ghcr.io/foundry-rs/foundry:latest` (includes forge/cast/anvil, NOT jq/curl).
- Volume permissions: use `:z` (shared SELinux label) for multi-container mounts.
## Testing & Analysis Suite
- Fuzzing scripts under `analysis/` support configurable trade/stake biases, adversarial attack patterns, background LP competition, and parameter sweeps. See `analysis/README.md` for full details.
- Adversarial testing (`run-adversarial.sh`, `run-v3-adversarial.sh`) validates floor defense against sell-heavy attacks.
- Background LP fee analysis (`run-bglp-fee-test.sh`) measures fee retention under LP competition.
- On-chain LP scanner (`scan-final.py`) compares real Uniswap V3 LP distributions to the BackgroundLP model.
- Recorded artifacts include CSV tick traces, frontier maps, and human-readable summaries for exploit triage.
## Guardrails & Conventions
- Respect access controls (`onlyLiquidityManager`, owner) and avoid editing implementation helpers like LiquidityProvider or ThreePositionStrategy.
- Debug tips: inspect position CSVs, verify token type assumptions, and check VWAP recording direction during simulations.
- Staking positions tracked by `positionId`; tax rates drawn from discrete array within Stake.sol.
## Guardrails
- Respect access controls (`onlyLiquidityManager`, owner).
- `token0isWeth` flips amount semantics — confirm ordering before interpreting liquidity.
- Floor uses `vwapX96` directly (not sqrt) in fixed-point math.
- Outstanding supply excludes LM position balances and KRK held by `feeDestination`/`stakingPool`.

View file

@ -1 +0,0 @@
AGENTS.md

View file

@ -1,171 +1,69 @@
## Foundry
# KRAIKEN Onchain
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
Solidity contracts for the KRAIKEN protocol. Built with Foundry.
Foundry consists of:
## Contracts
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
| Contract | Description |
|----------|-------------|
| `Kraiken.sol` | ERC20 token with mint/burn controlled by LiquidityManager. VERSION=2. |
| `LiquidityManager.sol` | Three-position Uniswap V3 strategy (Anchor, Discovery, Floor). |
| `Stake.sol` | Harberger-tax staking with snatching auctions and discrete tax brackets. |
| `OptimizerV3.sol` | UUPS upgradeable. Binary bear/bull parameter selection from staking sentiment. |
| `VWAPTracker.sol` | Volume-weighted average price with directional recording and compression. |
## Documentation
## Setup
https://book.getfoundry.sh/
## Usage
### Install
```shell
$ git clone
$ git submodule init
$ git submodule update
$ cd lib/uni-v3-lib
$ yarn
```bash
git submodule update --init --recursive
cd lib/uni-v3-lib && npm install && cd ../..
forge build
forge test
```
### Build
## Deploy
```shell
$ forge build
```
### Test
```shell
$ forge test
```
### Format
```shell
$ forge fmt
```
### Gas Snapshots
```shell
$ forge snapshot
```
### Anvil
```shell
$ anvil
```
### Deploy
```shell
forge clean
forge cache clean
```bash
source .env
forge script script/BaseSepoliaDeploy.sol:BaseSepoliaDeploy --slow --broadcast --verify --rpc-url ${BASE_SEPOLIA_RPC_URL}
```
if verification fails:
```shell
forge verify-contract --watch --chain sepolia --constructor-args $(cast abi-encode "constructor(string,string,address,address,address)" "Kraiken" "KRAIKEN" "0x0227628f3F023bb0B980b67D528571c95c6DaC1c" "0xb16F35c0Ae2912430DAc15764477E179D9B9EbEa" "0x64dda11815b883c589afed914666ef2d63c8c338") 0x7517db0f2b24223f2f0e3567149ca180e204da8a Kraiken
See [docs/DEPLOYMENT_RUNBOOK.md](../docs/DEPLOYMENT_RUNBOOK.md) for production deployment.
forge verify-contract --watch --chain sepolia --constructor-args $(cast abi-encode "constructor(address)" "0x7517db0f2b24223f2f0e3567149ca180e204da8a") 0x00b4d656b8182d0c2f4841b7a6f1429b94f73a66 Stake
```
## Deployments
### Base Mainnet
| Contract | Address |
|----------|---------|
| Kraiken | `0x45caa5929f6ee038039984205bdecf968b954820` |
| Stake | `0xed70707fab05d973ad41eae8d17e2bcd36192cfc` |
| LiquidityManager | `0x7fd4e645ce258dd3942eddbeb2f99137da8ba13b` |
### Cast
```shell
$ cast <subcommand>
```
### Help
```shell
$ forge --help
$ anvil --help
$ cast --help
```
## Deployment on Base Sepolia
### Multisig
address: 0xf6a3eef9088A255c32b6aD2025f83E57291D9011
### Kraiken
address: 0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8
### Stake
address: 0xe28020BCdEeAf2779dd47c670A8eFC2973316EE2
### LP
address: 0x3d6a8797693a0bC598210782B6a889E11A2340Cd
## Deployment on Base
### Kraiken
address: 0x45caa5929f6ee038039984205bdecf968b954820
### Stake
address: 0xed70707fab05d973ad41eae8d17e2bcd36192cfc
### LP
address: 0x7fd4e645ce258dd3942eddbeb2f99137da8ba13b
### Base Sepolia
| Contract | Address |
|----------|---------|
| Kraiken | `0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8` |
| Stake | `0xe28020BCdEeAf2779dd47c670A8eFC2973316EE2` |
| LiquidityManager | `0x3d6a8797693a0bC598210782B6a889E11A2340Cd` |
## Research & Analysis
See [`analysis/KRAIKEN_RESEARCH_REPORT.md`](analysis/KRAIKEN_RESEARCH_REPORT.md) for the comprehensive research report covering:
- Critical math bugs found and fixed (sqrt inflation + outstandingSupply)
- Floor drain vulnerability analysis and VWAP mirror defense
- Complete 2D parameter safety frontier (AS × AW)
- Fee revenue characterization and LP competition modeling
- OptimizerV3 design (direct 2D binary bear/bull mapping from Harberger staking data)
- Staking triangle cycle dynamics
The `analysis/` directory contains fuzzing scripts, parameter sweep tools, and security analysis:
The `analysis/` directory contains all fuzzing scripts, parameter sweep tools, and results data. See [`analysis/README.md`](analysis/README.md) for usage.
- [SECURITY_REVIEW.md](analysis/SECURITY_REVIEW.md) — Security analysis and vulnerability assessment
- [KRAIKEN_RESEARCH_REPORT.md](analysis/KRAIKEN_RESEARCH_REPORT.md) — Comprehensive research report
- [README.md](analysis/README.md) — Analysis tool usage guide
Key findings: critical sqrt price bug fixed, 1050-combo 4D parameter sweep completed, floor ratchet vulnerability identified. See the research report for details.
## ABI Architecture
Contract ABIs flow through the stack via `kraiken-lib/src/abis.ts`, which imports directly from `out/` (forge build artifacts). Run `forge build` to update ABIs across all consumers (ponder, web-app).
## References
## Simulation data:
```json
{ "VWAP":0,
"comEthBal":1234,
"comHarbBal":0,
"comStakeShare":0,
"liquidity":[{
"liquidity":1234,
"tickLower":-123,
"tickUpper":124
}],
"startTime":1234,
"txns":[{
"action":5,"timeOffset":0,"x":0,"y":""},
{"action":0,"ethAmount":1,"x":0,"y":""},
{"action":5,"timeOffset":0,"x":0,"y":""},
{"action":0,"ethAmount":2,"x":0,"y":""},
{"action":5,"timeOffset":0,"x":0,"y":""},
{"action":0,"ethAmount":4,"x":0,"y":""},
{"action":2,"harbAmount":3000,"tax":10,"y":""},
{"action":5,"timeOffset":0,"x":0,"y":""},
{"action":4,"positionId":654321,"x":0,"y":""},
{"action":2,"harbAmount":5000,"tax":20,"y":""},
{"action":0,"ethAmount":8,"x":0,"y":""},
{"action":5,"timeOffset":0,"x":0,"y":""},
{"action":1,"harbAmount":20000,"x":0,"y":""},
{"action":5,"timeOffset":0,"x":0,"y":""},
{"action":4,"positionId":654321,"x":0,"y":""},
{"action":2,"harbAmount":8000,"tax":29,"y":""}
]
}
```
- [AGENTS.md](AGENTS.md) — Agent guide for onchain development
- [UNISWAP_V3_MATH.md](UNISWAP_V3_MATH.md) — Uniswap V3 math reference
- [hAIrberger.md](hAIrberger.md) — Dynamic LP strategy design document

View file

@ -1,61 +0,0 @@
# Testing Todo List
## High Priority
- [x] ~~Break down testDoubleOverflowRealisticScenario() into 3 separate tests with assertions~~ ✅ **COMPLETED**
- [x] ~~**🔥 CRITICAL: Create Position Dependency Order Test** - verify _set() function order ANCHOR → DISCOVERY → FLOOR with correct dependencies~~ ✅ **COMPLETED**
- *Implemented as anchor-discovery contiguity checking in existing test infrastructure*
- *Added tick range validation to checkLiquidity() function and _validateRecenterResult()*
- *Correctly handles both token orderings (WETH as token0 vs token1)*
- [x] ~~**🔥 NEXT CRITICAL: Add assertions to testRecordVolumeAndPriceUnsafe()** - should assert recording behavior and overflow detection~~ ✅ **COMPLETED**
- *Implemented proper contract interaction with before/after state validation*
- *Added assertions for normal recording, compression, and extreme transaction capping*
- *Validates VWAP calculation accuracy and handles different overflow scenarios*
- *Now properly tests contract behavior instead of just logging calculations*
- [x] ~~Add assertions to testAttemptToCreateDoubleOverflow() - should assert expected overflow behavior instead of just logging~~ ✅ **COMPLETED via cleanup**
- *Duplicate functionality removed - VWAPTracker.t.sol already contains proper assertion-based double overflow tests*
- *Eliminated VWAPDoubleOverflowAnalysis.t.sol entirely - 100% duplicate of VWAPTracker.t.sol*
- *Proper tests with assertions already exist: testDoubleOverflowExtremeEthPriceScenario(), testDoubleOverflowHyperinflatedHarbScenario(), testDoubleOverflowMaximumTransactionScenario()*
## Medium Priority
- [ ] Create Floor Position VWAP Exclusivity Test - prove only floor position uses VWAP, anchor/discovery use current tick
- *Moved from High Priority - VWAP exclusivity not critical as long as floor correctly uses VWAP*
- [ ] Create EthScarcity vs EthAbundance Scenarios Test - test event emission and VWAP application logic
- [ ] Complete LiquidityManager integration tests - comprehensive test suite exercising full contract
- [ ] Create Floor Position Discount Verification Test - verify floor position pricing uses adjusted VWAP (70% + capital inefficiency)
- [ ] Validate gas usage equivalent to original LiquidityManager contract
## Low Priority
- [ ] Create Cross-Position Independence Test - verify anchor/discovery positions unaffected by VWAP changes
- [ ] Convert UniswapMath to library for better reusability
- [ ] Create interfaces for position strategies
- [ ] Design plugin architecture for swappable position strategies
- [ ] Add enhanced monitoring with granular events per component
## Code Organization Improvements ✅ **COMPLETED**
- [x] ~~DELETE VWAPDoubleOverflowAnalysis.t.sol - 100% duplicate functionality~~ ✅ **COMPLETED**
- [x] ~~RENAME ModularComponentsTest.t.sol → CompilationValidation.t.sol~~ ✅ **COMPLETED**
- [x] ~~All tests verified passing after cleanup~~ ✅ **COMPLETED**
## Progress Summary
- **Completed**: 4/15 tasks (27%) + 3 cleanup tasks
- **High Priority Remaining**: 1/6 tasks (testExtremeExpensiveHarbHandling - doesn't exist)
- **Medium Priority Remaining**: 5/5 tasks
- **Low Priority Remaining**: 5/5 tasks
## Priority Analysis (Post-Test Consolidation)
**COMPLETED**: Position Dependency Order Test - Successfully implemented as anchor-discovery contiguity checking
**COMPLETED**: testRecordVolumeAndPriceUnsafe() Assertions - Now properly tests VWAP contract behavior:
- Fuzzing test with 257 runs validates recording behavior and overflow detection
- Asserts normal recording, compression triggers, and extreme transaction capping
- Validates VWAP calculation accuracy across different scenarios
- Tests actual contract interface instead of just mathematical calculations
**NEXT PRIORITY**: Add assertions to testAttemptToCreateDoubleOverflow() - Convert logging-only test to proper assertions
## Recent Completion
**Break down testDoubleOverflowRealisticScenario()** - Successfully split into 3 focused tests with proper assertions:
- `testDoubleOverflowExtremeEthPriceScenario()` - ETH at $1M, KRAIKEN at $1
- `testDoubleOverflowHyperinflatedHarbScenario()` - KRAIKEN at $1M, ETH at $3k
- `testDoubleOverflowMaximumTransactionScenario()` - 10k ETH transactions
All new tests validate that double overflow requires unrealistic conditions, proving the 1000x compression limit provides adequate protection.

View file

@ -1 +0,0 @@
AGENTS.md

View file

@ -126,69 +126,17 @@ Once running, access the GraphQL playground at `http://localhost:42069/graphql`
- Projection calculation using median smoothing
- Rolling 24h and 7d aggregations
## Comparison with Subgraph
| Feature | Subgraph | Ponder |
|---------|----------|---------|
| Sync Speed | 1x | 10-15x faster |
| Hot Reload | ❌ | ✅ |
| Language | AssemblyScript | TypeScript |
| Setup | Complex (PostgreSQL, IPFS, Graph Node) | Simple (Node.js) |
| NPM Packages | ❌ | ✅ |
| Type Safety | Requires codegen | Automatic |
## Deployment Options
### Railway (Recommended)
```bash
npm run build
# Deploy to Railway with DATABASE_URL configured
```
## Deployment
### Self-Hosted
```bash
DATABASE_URL=postgresql://... npm run start
DATABASE_URL=postgresql://... PONDER_NETWORK=BASE npm run start
```
### Docker
```dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
ENV PONDER_NETWORK=BASE
CMD ["npm", "run", "start"]
```
## Troubleshooting
### Issue: "No chain configured"
**Solution**: Ensure `PONDER_NETWORK` is set correctly in `.env`
### Issue: Slow initial sync
**Solution**: Provide a faster RPC URL via environment variables
### Issue: Database errors
**Solution**: For production, use PostgreSQL instead of SQLite:
```bash
DATABASE_URL=postgresql://user:pass@host:5432/db npm run start
```
## Migration from Subgraph
This Ponder implementation maintains complete parity with the original subgraph:
- Same entity structure (Stats, Positions)
- Identical ring buffer logic
- Same tax rate mappings
- Compatible GraphQL queries
Key improvements:
- 10-15x faster indexing
- No Docker/Graph Node required
- Hot reload for development
- Direct SQL access for complex queries
- Full Node.js ecosystem access
### Troubleshooting
- **"No chain configured"**: Ensure `PONDER_NETWORK` is set in `.env`
- **Slow initial sync**: Provide a faster RPC URL
- **Database errors**: Use PostgreSQL for production (`DATABASE_URL` env var)
## License

View file

@ -9,270 +9,46 @@ Vue 3 + TypeScript staking interface for KRAIKEN, enabling users to stake tokens
- Axios for GraphQL queries to Ponder indexer
- Sass-based component styling
## Architecture Overview
## Architecture
### Chain Configuration Service
**Location**: `src/services/chainConfig.ts`
Centralizes all endpoint resolution for different blockchain networks. This service eliminates scattered configuration and provides a single source of truth for network-specific URLs.
**Key Method**:
```typescript
chainConfigService.getEndpoint(chainId: number, type: 'graphql' | 'rpc' | 'txnBot'): string
```
**Supported Chains**:
- `31337` - Local Anvil fork (development)
- `84532` - Base Sepolia (testnet)
- `8453` - Base Mainnet (production)
**Usage Pattern**:
```typescript
// Composables receive chainId and resolve endpoints internally
const endpoint = chainConfigService.getEndpoint(chainId, 'graphql');
```
**Benefits**:
- Single source of truth for all endpoint configuration
- Easy to test composables with different chainIds
- No hidden global state dependencies
- Clear error messages when endpoints aren't configured
### Chain Configuration
`src/services/chainConfig.ts` centralizes endpoint resolution. All composables accept `chainId` as a parameter and resolve endpoints via `chainConfigService.getEndpoint(chainId, type)`. Supported chains: 31337 (Anvil), 84532 (Base Sepolia), 8453 (Base Mainnet).
### Wagmi Integration
`src/wagmi.ts` manages wallet connection. Wagmi is the source of truth for which chain the wallet is on. Composables don't import wallet state directly — they accept `chainId` for testability.
**Configuration**: `src/wagmi.ts`
### Key Composables
- `useWallet()` — Wallet connection, balance, account state
- `usePositions(chainId)` — Loads staking positions from Ponder GraphQL
- `useStatCollection(chainId)` — Protocol-wide statistics
- `useSnatchSelection(demo, taxRateIndex, chainId)` — Calculates snatchable positions
- `useStake()` — Executes staking transactions
- `useAdjustTaxRate()` — Tax rate adjustment
- `useUnstake()` — Position exit transactions
Wagmi manages wallet connection and tracks the user's active blockchain:
- Wallet providers: WalletConnect, Coinbase Wallet
- Supported chains: Local fork (31337), Base Sepolia (84532)
- State persistence via localStorage
**Chain Determination Flow**:
1. Wagmi detects wallet's current chain via `watchChainId()`
2. `useWallet` exposes `account.chainId` from wagmi state
3. Components read `account.chainId` and pass to composables
4. Composables watch for chain changes independently and reload data
5. `ChainConfigService` maps chainId → endpoint URLs
**Key Insight**: Wagmi is the source of truth for *which chain the wallet is on*, but composables don't import wallet state directly. They accept `chainId` as a parameter for better testability and explicit dependencies.
## Key Composables
### `useWallet()`
**Purpose**: Manages wallet connection, balance, and account state
**Exports**: `balance`, `account`, `loadBalance()`
**Watchers**:
- `watchAccount()` - Reloads balance when account/chain changes
- `watchChainId()` - Reloads balance on chain switch
**Note**: Also exports `chainData` computed property for UI metadata (Uniswap links, chain names). This is separate from endpoint resolution, which goes through `ChainConfigService`.
### `usePositions(chainId: number)`
**Purpose**: Loads and manages staking positions from Ponder GraphQL
**Parameters**: `chainId` - Which chain to query positions from
**Exports**: `activePositions`, `myActivePositions`, `myClosedPositions`, `tresholdValue`, `positionsError`, `loading`
**Key Features**:
- Watches contract events (`PositionCreated`, `PositionRemoved`) to auto-refresh
- Independent `watchChainId()` listener reloads on chain switch
- Exponential backoff retry on GraphQL failures (1.5s → 60s max)
**Data Flow**:
```
Component (chainId) → usePositions(chainId)
→ resolveGraphqlEndpoint(chainId)
→ chainConfigService.getEndpoint(chainId, 'graphql')
→ axios.post(endpoint, query)
```
### `useStatCollection(chainId: number)`
**Purpose**: Loads protocol-wide statistics (total supply, outstanding stake, inflation, etc.)
**Parameters**: `chainId` - Which chain to query stats from
**Exports**: `kraikenTotalSupply`, `stakeTotalSupply`, `outstandingStake`, `profit7d`, `inflation7d`, `maxSlots`, `claimedSlots`, `statsError`, `loading`
**Retry Logic**: Same exponential backoff as `usePositions`
### `useSnatchSelection(demo, taxRateIndex, chainId)`
**Purpose**: Calculates which positions can be "snatched" based on staking amount and tax rate
**Parameters**:
- `demo` - Include own positions in selection
- `taxRateIndex` - Maximum tax rate index to snatch
- `chainId` - Optional chain ID
**Dependencies**: `usePositions`, `useStatCollection`, `useStake`
**Exports**: `snatchablePositions`, `shortfallShares`, `floorTax`, `openPositionsAvailable`
### `useStake()`
**Purpose**: Executes staking transactions (stake, snatch-and-stake)
**Contract Interaction**: Calls `Stake.sol` via wagmi/viem
**State Management**: Tracks transaction states (StakeAble, SignTransaction, Waiting)
### `useAdjustTaxRate()`
**Purpose**: Provides tax rate options and handles tax rate adjustments
**Key Data**: `taxRates` array with pre-calculated yearly/daily rates
### `useUnstake()`
**Purpose**: Handles position exit transactions
**Contract Interaction**: Calls `exitPosition()` on Stake contract
## Key Components
### `StakeView.vue`
**Route**: `/dashboard`
**Purpose**: Main staking dashboard showing chart, statistics, active positions
**Key Features**:
- Passes `initialChainId` to all composables for consistent data loading
- Displays chain support status
- Shows "Connect Wallet" prompt when disconnected
### `StakeHolder.vue`
**Purpose**: Staking form with accessibility-focused UI
**Key Elements**:
- Token amount slider with ARIA labels
- Tax rate selector dropdown
- Real-time feedback (floor tax, positions buyout count)
- Action button with state-driven labels (Stake / Snatch and Stake / Sign Transaction / Waiting)
**Accessibility**:
- Semantic HTML with proper ARIA attributes
- Screen reader announcements for dynamic content
- Keyboard navigation support
**Test Hooks** (for Playwright):
- `page.getByRole('slider', { name: 'Token Amount' })`
- `page.getByLabel('Staking Amount')`
- `page.getByLabel('Tax')`
### `ConnectWallet.vue`
**Purpose**: Wallet connection modal with connector selection
**Features**:
- Shows connected wallet with avatar (blockies) and address
- Token balance display ($KRK, Staked $KRK)
- Buy button with chain-specific Uniswap link (uses `chainData.uniswap`)
### `ChartComplete.vue`
**Purpose**: Position visualization showing tax rates and snatchable positions
**Dependencies**: `usePositions`, `useStatCollection`, `useStake`
### `CollapseActive.vue`
**Purpose**: Expandable position card with profit calculation and actions
**Actions**: Pay Tax, Adjust Tax Rate, Unstake
## Shared Utilities
### `src/utils/logger.ts`
Structured logging with namespaces (contract, info, error)
### `src/utils/helper.ts`
Common helpers:
- `bigInt2Number(value, decimals)` - Convert Wei to human-readable
- `formatBigIntDivision(a, b)` - Safe BigInt division
- `compactNumber(n)` - Format large numbers (1.5M, 3.2K)
### `src/config.ts`
Chain configuration data:
- `chainsData` - Array of chain metadata (id, graphql, contracts, etc.)
- `getChain(id)` - Lookup chain by ID
- `DEFAULT_CHAIN_ID` - Auto-detected based on environment/hostname
## Contract Interfaces
### `src/contracts/harb.ts`
**Contract**: Kraiken.sol
**Methods**: `getMinStake()`, `getAllowance()`, `getNonce()`, `approve()`
**Setup**: `setHarbContract()` updates contract address when chain changes
### `src/contracts/stake.ts`
**Contract**: Stake.sol
**Methods**: `assetsToShares()`, `getTaxDue()`, `payTax(positionId)`
**Setup**: `setStakeContract()` updates contract address when chain changes
## Retry Logic & Error Handling
Both `usePositions` and `useStatCollection` implement **exponential backoff retry** for GraphQL failures:
**Configuration**:
- Base delay: 1.5 seconds
- Max delay: 60 seconds
- Backoff multiplier: 2x (1.5s → 3s → 6s → 12s → 24s → 48s → 60s)
**Why Retry**:
- Ponder indexer may not be ready during stack startup
- Temporary network issues shouldn't permanently break UI
- Chain switching endpoints may have brief response delays
**Implementation** (duplicated in both files):
- `formatGraphqlError()` - Parse Axios errors into user-friendly messages
- `clearXxxRetryTimer()` - Cancel pending retry
- `scheduleXxxRetry()` - Queue retry with exponential backoff
- `resolveGraphqlEndpoint()` - Resolve chainId to GraphQL URL
**Refactoring Opportunity**: ~41 lines of duplicate code could be extracted to `src/utils/graphqlRetry.ts`
### Key Components
- `StakeView.vue` — Main staking dashboard (route: `/dashboard`)
- `StakeHolder.vue` — Staking form with accessibility-focused UI
- `ConnectWallet.vue` — Wallet connection modal
- `ChartComplete.vue` — Position visualization
- `CollapseActive.vue` — Expandable position card with actions
## Development Workflow
### Running Locally
Boot the full stack with `./scripts/dev.sh start` (see root `CLAUDE.md` for details)
### Targeted Development
- `npm run dev` - Vite dev server (assumes Ponder/Anvil already running)
- `npm run build` - Production build with type checking
- `npm run preview` - Preview production build
- `npm run test:e2e` - Playwright E2E tests (from repo root)
### Live Reload
Use `./scripts/watch-kraiken-lib.sh` to rebuild `kraiken-lib` on file changes and auto-restart dependent containers
- Boot full stack: `./scripts/dev.sh start` (see root AGENTS.md)
- Targeted: `npm run dev` (assumes Ponder/Anvil already running)
- Build: `npm run build`
- E2E tests: `npm run test:e2e` from repo root (Playwright)
## Testing
### E2E Tests
**Location**: `tests/e2e/` (repo root)
**Framework**: Playwright
**Coverage**: Complete user journeys (mint ETH → swap KRK → stake)
**CI**: Woodpecker e2e pipeline runs these against pre-built service images
**Test Strategy**:
- Use mocked wallet provider with Anvil accounts
- Tests automatically start/stop the full stack
- Rely on semantic HTML and ARIA attributes (not private selectors)
### Manual Testing Checklist
1. Connect wallet (WalletConnect / Coinbase Wallet)
2. Switch chains and verify data reloads
3. Stake tokens with different tax rates
4. Snatch positions with higher tax rate
5. Adjust tax rate on existing position
6. Pay tax manually
7. Unstake position
8. Verify GraphQL error retry behavior (kill Ponder, observe retries)
- E2E tests in `tests/e2e/` (repo root) cover complete user journeys
- Uses mocked wallet provider with Anvil accounts
- Relies on semantic HTML and ARIA attributes for selectors
- StakeHolder test hooks: `page.getByRole('slider', { name: 'Token Amount' })`, `page.getByLabel('Tax')`
## Quality Guidelines
- **Composables**: Accept `chainId` parameter instead of importing wallet state directly
- **Watchers**: Each composable maintains its own `watchChainId()` listener for independence
- **Error States**: Always expose `xxxError` and `loading` refs for UI feedback
- **Type Safety**: Use strongly typed interfaces for Position, StatsRecord, etc.
- **Accessibility**: Use semantic HTML, ARIA attributes, and keyboard navigation
- **Testability**: Design components to work with Playwright role/label selectors
## Performance Tips
- Lazy load routes with Vue Router dynamic imports
- Debounce `assetsToShares()` calls in StakeHolder (500ms)
- Use `computed()` for derived state to avoid recalculation
- Clear watchers in `onUnmounted()` to prevent memory leaks
- Cancel retry timers on unmount or manual actions
## Common Pitfalls
1. **Don't** import `chainData` from `useWallet` in composables - pass `chainId` explicitly
2. **Don't** forget to pass `chainId` to `loadPositions()` / `loadStats()` on manual refresh
3. **Don't** call composables conditionally - they must run on every component render
4. **Don't** forget to clear timers/watchers in `onUnmounted()`
5. **Do** reset retry delays on successful loads (`retryDelayMs.value = BASE_DELAY`)
## Future Enhancements
- Extract retry logic to shared utility (`src/utils/graphqlRetry.ts`)
- Remove dead code in `useChain.ts` (entire file is commented out)
- Clean up commented debug `console.log()` statements
- Implement three-way version validation (contract VERSION ↔ Ponder ↔ web-app)
- Add GraphQL query caching layer for better performance
- Composables accept `chainId` parameter instead of importing wallet state directly
- Each composable maintains its own `watchChainId()` listener for independence
- Always expose `xxxError` and `loading` refs for UI feedback
- Use strongly typed interfaces for Position, StatsRecord, etc.
- Use semantic HTML, ARIA attributes, and keyboard navigation
- Clear watchers and retry timers in `onUnmounted()`