Commit graph

15 commits

Author SHA1 Message Date
johba
d2c1e83962 fix: testMomentumFullBearAtNegMaxDelta has no slot assertions (#1011)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:50:41 +00:00
johba
636ba989ee fix: Optimizer and OptimizerV3 lack _disableInitializers() in constructor (#1055) (#1080)
Fixes #1055

## Changes
That notification is for the earlier background task which already completed — I retrieved its output and used it to diagnose and fix the failing test. The work is done.

Reviewed-on: https://codeberg.org/johba/harb/pulls/1080
Reviewed-by: Disinto_bot <disinto_bot@noreply.codeberg.org>
2026-03-21 13:42:54 +01:00
openhands
42b4bf4149 fix: Shift field silently ignored — dyadic rational inputs effectively unsupported (#606)
Add require(shift == 0) guards to Optimizer.calculateParams and
OptimizerV3.calculateParams so non-zero shifts revert instead of being
silently discarded.  OptimizerV3Push3 already had this guard.

Update IOptimizer.sol NatSpec to document that shift is reserved for
future use and must be 0 in all current implementations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:42:50 +00:00
openhands
e28e69c98a fix: guard int128 overflow in ThreePositionStrategy mirror tick (#622)
Move overflow guard to the actual vulnerable site:
ThreePositionStrategy._computeFloorTickWithSignal() line 262 where
vwapX96 >> 32 is cast to int128 for _tickAtPriceRatio. Values
exceeding int128.max now skip mirror tick (fallback to scarcity/clamp)
instead of reverting.

Remove incorrect require from Optimizer._buildInputs() which guarded
a non-existent int256 cast path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 02:46:30 +00:00
openhands
7007e593da fix: getLiquidityParams: int256 overflow on large VWAP values (#622)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 02:05:25 +00:00
openhands
bb150671ea fix: OptimizerInputCapture test harness is structurally broken (#652)
The pure override in OptimizerInputCapture could not write to storage,
and getLiquidityParams calls calculateParams via staticcall which
prevents both storage writes and event emissions.

Fix: extract the input-building normalization from getLiquidityParams
into _buildInputs() (internal view, behavior-preserving refactor).
The test harness now exposes _buildInputs() via getComputedInputs(),
allowing tests to assert actual normalized slot values.

Updated tests for pricePosition, timeSinceRecenter, volatility,
momentum, and utilizationRate to assert non-zero captured values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:57:25 +00:00
openhands
28ce5ec8cd fix: Optimizer.sol base class only guards slots 0 and 1 (#968)
Replace the two per-slot require checks with a loop over all 8 input slots
so future subclasses using slots 2-7 are protected from silent uint256 wrap.
Add testCalculateParamsRevertsOnNegativeMantissaSlots2to7 to verify the guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 18:24:18 +00:00
johba
8064623a54 fix: feat: Push3 input redesign — normalized indicators instead of raw protocol values (#635) (#649)
Fixes #635

## Changes
The implementation is complete and committed. All 211 tests pass.

## Summary of changes

### `onchain/src/Optimizer.sol`
- **Replaced raw slot inputs** with normalized indicators in `getLiquidityParams()`:
  - Slot 2 `pricePosition`: where current price sits within VWAP ± 11 000 ticks (0 = lower bound, 0.5e18 = at VWAP, 1e18 = upper bound)
  - Slot 3 `volatility`: `|shortTwap − longTwap| / 1000 ticks`, capped at 1e18
  - Slot 4 `momentum`: 0 = falling, 0.5e18 = flat, 1e18 = rising (5-min vs 30-min TWAP delta)
  - Slot 5 `timeSinceRecenter`: `elapsed / 86400s`, capped at 1e18
  - Slot 6 `utilizationRate`: 1e18 if current tick is within anchor position range, else 0
- **Extended `setDataSources()`** to accept `liquidityManager` + `token0isWeth` (needed for correct tick direction in momentum/utilizationRate)
- **Added `_vwapToTick()`** helper: converts `vwapX96 = price × 2⁹⁶` to tick via `sqrt(vwapX96) << 48`, with TickMath bounds clamping
- All slots gracefully default to 0 when data sources are unconfigured or TWAP history is insufficient (try/catch on `pool.observe()`)

### `onchain/src/OptimizerV3Push3.sol`
- Updated NatSpec to document the new `[0, 1e18]` slot semantics

### New tests (`onchain/test/`)
- `OptimizerNormalizedInputsTest`: 18 tests covering all new slots, token ordering, TWAP fallback, and a bounded fuzz test
- `mocks/MockPool.sol`: configurable `slot0()` + `observe()` with TWAP tick math
- `mocks/MockLiquidityManagerPositions.sol`: configurable anchor position bounds

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/649
Reviewed-by: review_bot <review_bot@noreply.codeberg.org>
2026-03-13 07:53:46 +01:00
openhands
9bb223cf95 fix: Optimizer.sol also silently accepts negative mantissa inputs (#582)
Add require(mantissa >= 0) guards in calculateParams before the uint256()
casts on inputs[0] and inputs[1], preventing negative int256 values from
wrapping to huge uint256 numbers and corrupting liquidity calculations.
Add two regression tests covering the revert paths for both slots.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 15:41:39 +00:00
openhands
cfcf750084 fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
  recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
  token amounts (via LiquidityAmounts math), fees (proportional to
  liquidity share), IL (LP exit value − HODL value at exit price), and
  net P&L per position. Aggregates total fees, cumulative IL, net P&L,
  rebalance count, Anchor time-in-range, and capital efficiency accumulators.
  Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.

- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
  constructor (creates PositionTracker internally), call
  tracker.notifyBlock() on every block for time-in-range, and call
  tracker.recordRecenter() on each successful recenter. logSummary()
  now delegates to tracker.logFinalSummary().

- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
  StrategyExecutor constructor; log tracker address.

- forge fmt: reformat all backtesting scripts and affected src/test files
  to project style (number_underscore=thousands, multiline_func_header=all).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00: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
d7c2184ccf Add Solidity linting with solhint, Foundry formatter, and pre-commit hooks (#51)
## Changes

### Configuration
- Added .solhint.json with recommended rules + custom config
  - 160 char line length (warn)
  - Double quotes enforcement (error)
  - Explicit visibility required (error)
  - Console statements allowed (scripts/tests need them)
  - Gas optimization warnings enabled
  - Ignores test/helpers/, lib/, out/, cache/, broadcast/

- Added foundry.toml [fmt] section
  - 160 char line length
  - 4-space tabs
  - Double quotes
  - Thousands separators for numbers
  - Sort imports enabled

- Added .lintstagedrc.json for pre-commit auto-fix
  - Runs solhint --fix on .sol files
  - Runs forge fmt on .sol files

- Added husky pre-commit hook via lint-staged

### NPM Scripts
- lint:sol - run solhint
- lint:sol:fix - auto-fix solhint issues
- format:sol - format with forge fmt
- format:sol:check - check formatting
- lint / lint:fix - combined commands

### Code Changes
- Added explicit visibility modifiers (internal) to constants in scripts and tests
- Fixed quote style in DeployLocal.sol
- All Solidity files formatted with forge fmt

## Verification
-  forge fmt --check passes
-  No solhint errors (warnings only)
-  forge build succeeds
-  forge test passes (107/107)

resolves #44

Co-authored-by: johba <johba@harb.eth>
Reviewed-on: https://codeberg.org/johba/harb/pulls/51
2025-10-04 15:17:09 +02:00
Your Name
0de1cffea8 another fixup of fuzzer 2025-09-16 22:46:43 +02:00
johba
db23d756e9 fix: Optimize fuzzing and fix CSV buffer accumulation
- Deploy Uniswap factory once before all runs (saves ~1.16M gas per run)
- Fix CSV buffer accumulation bug by clearing buffer between runs
- Add clearCSV() function to CSVManager for proper buffer management
- Each fuzzing run now gets its own clean CSV with correct token0isWeth values
- Comment out failing console.log in Optimizer.t.sol to fix compilation

The token ordering now correctly alternates:
- Even seeds: token0isWeth = true (WETH < KRAIKEN)
- Odd seeds: token0isWeth = false (KRAIKEN < WETH)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 13:30:18 +02:00
johba
f3047072f6 feat: Dynamic anchorWidth based on staking metrics
Replace hardcoded anchorWidth=100 with dynamic calculation that uses staking data as a decentralized oracle.

Changes:
- Add _calculateAnchorWidth() function to Optimizer.sol
- Base width 40% with adjustments based on staking percentage and average tax rate
- Staking adjustment: -20% to +20% (inverse relationship)
- Tax rate adjustment: -10% to +30% (direct relationship)
- Final range clamped to 10-80% for safety

Rationale:
- High staking % = bullish sentiment → narrower anchor (20-35%) for fee optimization
- Low staking % = bearish/uncertain → wider anchor (60-80%) for defensive positioning
- High tax rates = volatility expected → wider anchor to reduce rebalancing
- Low tax rates = stability expected → narrower anchor for fee collection

The Harberger tax mechanism acts as a prediction market where stakers' self-assessed valuations reveal market expectations.

Tests:
- Add comprehensive unit tests in test/Optimizer.t.sol
- Add mock contracts for testing (MockStake.sol, MockKraiken.sol)
- Manual verification confirms all scenarios calculate correctly

Documentation:
- Add detailed analysis of anchorWidth price ranges
- Add staking-based strategy recommendations
- Add verification of calculation logic

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 11:41:02 +02:00