Commit graph

485 commits

Author SHA1 Message Date
johba
19df05843d Merge pull request 'fix: Backtesting #4: Deploy KrAIken contracts + recenter execution loop (#318)' (#349) from fix/issue-318 into master 2026-02-27 10:26:12 +01:00
johba
1f019ddacc Merge pull request 'fix: uint256ToBytesLittleEndian silently truncates above 2³²−1 (#294)' (#337) from fix/issue-294 into master 2026-02-27 10:20:02 +01:00
openhands
84203294af fix: Backtesting #4: Deploy KrAIken contracts + recenter execution loop (#318)
- Add BacktestKraiken.sol: extends MockToken with Kraiken-compatible interface
  (dual mint overloads — public mint(address,uint256) for EventReplayer and
  restricted mint(uint256) for LiquidityManager; peripheryContracts() stubs
  staking pool as address(0))

- Add KrAIkenDeployer.sol: library deploying OptimizerV3Push3 + LiquidityManager
  on the shadow pool, wiring BacktestKraiken permissions, setting fee destination,
  and funding LM with configurable initial mock-WETH capital (default 10 ETH)

- Add StrategyExecutor.sol: time-based recenter trigger (configurable block
  interval, default 100 blocks); logs block, pre/post positions (Floor/Anchor/
  Discovery tick ranges + liquidity), fees collected, and revert reason on skip;
  negligible-impact assumption documented as TODO(#319)

- Modify EventReplayer.sol: add overloaded replay() accepting an optional
  StrategyExecutor hook; maybeRecenter() called after each block advancement
  without halting replay on failure

- Modify BacktestRunner.s.sol: replace tokenA/B with MockWETH + BacktestKraiken,
  integrate KrAIkenDeployer + StrategyExecutor into broadcast block; configurable
  via RECENTER_INTERVAL and INITIAL_CAPITAL_WETH env vars; executor.logSummary()
  printed after replay

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 09:00:22 +00:00
johba
2ffdd55b4c Merge pull request 'fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)' (#334) from fix/issue-317 into master 2026-02-27 09:40:03 +01:00
johba
b8e48a3d33 Merge pull request 'fix: Landing cleanup: 404 route, German comments, dead code, orphaned heading (#306)' (#346) from fix/issue-306 into master 2026-02-27 09:26:19 +01:00
openhands
17b100ef2a fix: address AI review feedback (round 2) for #317 event replay
- Guard final drift sample with `idx % LOG_INTERVAL != 0` to prevent
  double-counting stats when totalReplayed is an exact multiple of
  LOG_INTERVAL (the loop's _logCheckpoint already fired for that state)
- Hoist pool.slot0() before the guard and pass finalSqrtPrice/finalTick
  to _logSummary(), eliminating the redundant slot0 read inside it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:55:53 +00:00
openhands
1e6f817cf4 fix: Landing cleanup: 404 route, German comments, dead code, orphaned heading (#306)
- Add /:pathMatch(.*)*  catch-all route that redirects to / so unknown
  URLs no longer render blank
- Replace German inline comments in scrollBehavior with English equivalents
- Remove seven dead `// group: "navbar"` comments from /docs route and its
  child routes (the live group: 'navbar' property on the parent is kept)
- HomeView.vue and HomeViewMixed.vue already carry the renamed
  "Verified On-Chain" heading with supporting copy; no changes needed there

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:53:42 +00:00
openhands
ac32a1849c ci: retrigger after infra failure 2026-02-27 07:30:34 +00:00
johba
8c336ae0f5 Merge pull request 'fix: Stake.sol: exitPosition guard order (owner check before existence) (#307)' (#336) from fix/issue-307 into master 2026-02-27 08:14:09 +01:00
openhands
cd065275be fix: address AI review feedback for #317 event replay
- Cache pool.tickSpacing() as immutable in EventReplayer constructor
  to avoid a repeated external call per _replayMint() invocation
- Rename driftCount → driftCheckpoints for consistency with log label
- Add sqrtDriftBps to the per-checkpoint progress log line, using the
  now-live lastExpectedSqrtPrice field (previously written but never read)
- Guard _replaySwap(): skip and count events where amountSpecified ≤ 0,
  which would silently flip exact-input into exact-output mode
- Add a final drift sample after the while-loop for trailing events not
  covered by the last LOG_INTERVAL checkpoint
- Move EventReplayer construction outside the broadcast block in
  BacktestRunner (it uses vm.* cheat codes incompatible with real RPC)
- Change second vm.closeFile() from try/catch to a direct call so errors
  surface rather than being silently swallowed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:09:29 +00:00
openhands
49d7d708d1 fix: uint256ToBytesLittleEndian silently truncates above 2³²−1 (#294) 2026-02-27 06:43:08 +00:00
openhands
6eacfe1975 fix: \uint256ToBytesLittleEndian\ silently truncates above 2³²−1 (#294)
Expand the output buffer from 4 bytes to 32 bytes and iterate all 32
positions, so values ≥ 2³² are encoded correctly instead of silently
dropped. Update tests to assert 32-byte output and add coverage for
2³², 2¹²⁸, and max uint256 roundtrips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:42:59 +00:00
openhands
24fdcd3dcd fix: Stake.sol: exitPosition guard order (owner check before existence) (#307)
Check pos.creationTime == 0 before pos.owner != msg.sender so that
calling exitPosition on a non-existent position correctly reverts with
PositionNotFound instead of the misleading NoPermission(caller, 0x0).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:33:32 +00:00
openhands
a884f8a5c9 ci: retrigger after infra failure 2026-02-27 06:27:58 +00:00
johba
9341673a1a Merge pull request 'fix: Ponder: fix mintNextHourProjected divisor, dead param, dead code (#308)' (#333) from fix/issue-308 into master 2026-02-27 07:20:02 +01:00
openhands
a3eb406e46 fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:17:54 +00:00
openhands
896fffb2e8 fix: Backtesting #3: Replay historical Swap/Mint/Burn events against shadow pool (#317)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 06:12:03 +00:00
johba
00037dc713 Merge pull request 'fix: Backtesting #2: Foundry script skeleton + Uniswap V3 shadow pool deployment (#316)' (#332) from fix/issue-316 into master 2026-02-27 06:48:19 +01:00
openhands
a4a3a85fdc fix: Ponder: fix mintNextHourProjected divisor, dead param, dead code (#308) 2026-02-27 05:47:51 +00:00
openhands
70e49b2546 fix: suppress compiler warnings in BacktestRunner (#316)
- Add `view` to _parseSqrtPriceFromFile and _resolveSqrtPrice
- Remove unused IUniswapV3Pool import

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 05:12:45 +00:00
openhands
96b06bd9fe fix: Backtesting #2: Foundry script skeleton + Uniswap V3 shadow pool deployment (#316)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 05:08:27 +00:00
johba
c540d56d08 Merge pull request 'fix: Backtesting #1: Event fetcher (Infura → JSON Lines cache) (#315)' (#331) from fix/issue-315 into master 2026-02-27 00:12:51 +01:00
openhands
c33bdbaad5 fix: address review feedback on fetch-events.ts (#315)
- Replace hardcoded Infura API key with INFURA_API_KEY env var; fail fast
  with a helpful message if unset and no --rpc-url is given
- Add onchain/script/backtesting/.gitignore (cache/) instead of relying on
  the opaque root pattern; remove force-tracked cache/.gitkeep (mkdirSync
  creates the directory at runtime)
- Document resume constraint: reliable only when both --start-block and
  --end-block are explicit, or --output is set
- Fix batch-number display: derive batchNum inside the loop from the actual
  `from` block so it stays correct when resumeFromBlock isn't BATCH_SIZE-aligned
- Guard log.logIndex === null consistently with blockNumber/transactionHash
- console.warn on decode errors instead of silently discarding them

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 22:45:40 +00:00
openhands
df89b8c2da fix: Backtesting #1: Event fetcher (Infura → JSON Lines cache) (#315)
Add onchain/script/backtesting/fetch-events.ts — a tsx script that:
- Fetches Swap/Mint/Burn events from a Uniswap V3 pool via Infura (Base mainnet)
- Batches eth_getLogs in 2 000-block chunks with 100 ms inter-batch delay
- Decodes each log with viem and writes one JSON Line per event
- Supports resume: reads last block from existing cache file on re-run
- Retries with exponential back-off on 429 / rate-limit errors
- Prints per-batch progress: "Fetching blocks X-Y... N events (B/T batches)"

Also adds package.json, tsconfig.json, and cache/.gitkeep.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 22:04:43 +00:00
johba
52411e881a Merge pull request 'revert: Remove premature backtesting code (#320)' (#328) from revert/backtesting-320 into master
Reviewed-on: https://codeberg.org/johba/harb/pulls/328
2026-02-26 22:21:37 +01:00
johba
50f985ef6f Merge pull request 'fix: CollapseActive: null guard on total computed + remove redundant BigInt casts (#309)' (#327) from fix/issue-309 into master 2026-02-26 22:04:51 +01:00
openhands
4a6256b941 Revert "Merge pull request 'fix: Backtesting #6: Baseline strategies (HODL, full-range, fixed-width) + reporting (#320)' (#322) from fix/issue-320 into master"
This reverts commit 1e5ac0de80, reversing
changes made to 6526928b67.
2026-02-26 20:45:19 +00:00
openhands
63ddf14a5c fix: CollapseActive: null guard on total computed + remove redundant BigInt casts (#309)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:42:17 +00:00
johba
c73f0e8bc1 Merge pull request 'fix: Remove dead Optimizer V2/V3 — Push3 is the active optimizer (#312)' (#321) from fix/issue-312 into master 2026-02-26 20:57:52 +01:00
openhands
2a7afbf6d2 fix: Increase test stake amount to 1000 — base Optimizer wider anchor raises minStake 2026-02-26 19:37:12 +00:00
openhands
2d25200582 fix: Update E2E tests for Optimizer (base) — drop OptimizerV3 bear-market constants
- 01-acquire-and-stake: replace flat 3 s wait with a 30 s polling loop so
  Ponder indexing lag no longer causes a spurious positions.length=0 failure.

- 05-optimizer-integration test 1: replace hard-coded OptimizerV3 bear-market
  constants (anchorShare=3e17, anchorWidth=100, discoveryDepth=3e17) with
  Optimizer.sol invariant checks:
    capitalInefficiency + anchorShare == 1e18
    discoveryDepth == anchorShare
    anchorWidth ∈ [10, 80]

- 05-optimizer-integration test 2: decouple bootstrap-position assertion from
  current optimizer state.  Earlier tests change staking state, so the current
  optimizer anchorWidth differs from the one used at bootstrap time.  Instead,
  reverse-calculate the implied anchorWidth from the observed anchor spread and
  verify it lies within [10, 80].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 19:37:12 +00:00
openhands
d9bfedcfcc ci: retrigger after infra failure 2026-02-26 19:37:12 +00:00
openhands
99d9c563d6 fix: Use Optimizer (base) in deploy scripts — Push3 lacks initialize/getLiquidityParams
OptimizerV3Push3 is an equivalence-proof contract with only isBullMarket().
It cannot serve as an ERC1967Proxy implementation because it has no initialize()
or getLiquidityParams(). The CI bootstrap was failing because the proxy
deployment reverted when calling initialize() on the Push3 implementation.

Switch deploy scripts to Optimizer.sol (the base UUPS contract) which has the
full interface required by ERC1967Proxy and LiquidityManager.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 19:37:12 +00:00
openhands
e925538309 fix: Remove dead Optimizer V2/V3 — Push3 is the active optimizer (#312)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 19:37:12 +00:00
johba
1e5ac0de80 Merge pull request 'fix: Backtesting #6: Baseline strategies (HODL, full-range, fixed-width) + reporting (#320)' (#322) from fix/issue-320 into master 2026-02-26 18:02:54 +01:00
openhands
9061f8e8f6 fix: Address AI review findings for backtesting baseline strategies (#320)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 16:39:47 +00:00
openhands
5205ea6f4a fix: Backtesting #6: Baseline strategies (HODL, full-range, fixed-width) + reporting (#320)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 16:11:15 +00:00
johba
6526928b67 Merge pull request 'fix: Landing copy: fix immutable overclaim + sync Mixed variant floor copy (#310)' (#311) from fix/issue-310 into master 2026-02-26 15:02:46 +01:00
openhands
143d6b202a fix: Landing copy: fix immutable overclaim + sync Mixed variant floor copy (#310)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 13:40:34 +00:00
johba
ed24a166ab Merge pull request 'fix: Test coverage: Kraiken + VWAPTracker to 100% (#283)' (#303) from fix/issue-283 into master 2026-02-26 06:34:08 +01:00
openhands
e9370c143e fix: Test coverage: Kraiken + VWAPTracker to 100% (#283)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 05:12:48 +00:00
johba
2baa913435 Merge pull request 'fix: Test coverage: Stake.sol to 100% (#284)' (#298) from fix/issue-284 into master 2026-02-26 05:54:53 +01:00
openhands
cff95a3670 fix: Test coverage: Stake.sol to 100% (#284) 2026-02-26 04:28:47 +00:00
openhands
93ddd28978 fix: Test coverage: Stake.sol to 100% (#284)
Add 11 new targeted tests in Stake.t.sol to cover all reachable
uncovered branches and the untested permitAndSnatch() function:

- testRevert_TaxRateOutOfBounds_InSnatch: taxRate >= TAX_RATES.length in snatch()
- testRevert_PositionNotFound_NonLastInLoop: PositionNotFound inside the multi-position loop
- testRevert_TaxTooLow_NonLastInLoop: TaxTooLow inside the multi-position loop
- testSnatch_ExitLastPosition: _exitPosition() path for last snatched position
- testRevert_ExceededAvailableStake: no available stake, no positions provided
- testRevert_TooMuchSnatch_AvailableExceedsNeed: post-exit excess stake check
- testRevert_PositionNotFound_InChangeTax: changeTax() on non-existent position
- testRevert_TaxTooLow_InChangeTax: changeTax() with same/lower tax rate
- testRevert_NoPermission_InExitPosition: exitPosition() by non-owner
- testRevert_PositionNotFound_InPayTax: payTax() on non-existent position
- testPermitAndSnatch: EIP-712 permit + snatch in one transaction

Coverage achieved:
  Lines:     99.33% (148/149)
  Statements: 99.40% (167/168)
  Branches:  93.55% (29/31)  — 2 unreachable dead-code branches remain
  Functions: 100.00% (15/15)

The 2 uncovered branches are dead code: the require() failure in
_shrinkPosition (caller always guards sharesToTake < pos.share) and
the PositionNotFound guard in exitPosition() (unreachable because
owner and creationTime are always set/cleared together, so
pos.owner==msg.sender implies pos.creationTime!=0 for any live caller).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 03:59:20 +00:00
johba
a7947c64c8 Merge pull request 'fix: Test coverage: LiquidityManager + Optimizer + OptimizerV3 to 100% (#285)' (#296) from fix/issue-285 into master 2026-02-26 04:07:11 +01:00
openhands
9cce524b8a fix: Test coverage: LiquidityManager + Optimizer + OptimizerV3 to 100% (#285)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 02:41:02 +00:00
johba
b161b4ecfb Merge pull request 'fix: kraiken-lib: fix broken tests + raise coverage to 95% (#286)' (#293) from fix/issue-286 into master 2026-02-26 02:32:27 +01:00
openhands
dc95b2d22e fix: kraiken-lib: fix broken tests + raise coverage to 95% (#286)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 01:09:55 +00:00
openhands
2aa85f5a03 fix: CI failure in run-e2e-tests (#286) 2026-02-26 00:42:32 +00:00
openhands
e5bd4f29f7 fix: kraiken-lib: fix broken tests + raise coverage to 95% (#286)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 00:42:21 +00:00