From d3ff2cd0bf96a9e89d9d46d0b1d365d217e514e9 Mon Sep 17 00:00:00 2001 From: openhands Date: Thu, 19 Mar 2026 18:22:43 +0000 Subject: [PATCH] fix: Bear defaults duplicated across Optimizer and LiquidityManager (#646) Extract bear-mode default values (0, 3e17, 100, 3e17) into file-level constants in IOptimizer.sol so both Optimizer._bearDefaults() and LiquidityManager.recenter()'s catch block reference a single source of truth instead of independent hardcoded literals. Co-Authored-By: Claude Opus 4.6 (1M context) --- onchain/src/IOptimizer.sol | 8 ++++++++ onchain/src/LiquidityManager.sol | 10 +++++----- onchain/src/Optimizer.sol | 8 +++----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/onchain/src/IOptimizer.sol b/onchain/src/IOptimizer.sol index ccb68d5..047bcdd 100644 --- a/onchain/src/IOptimizer.sol +++ b/onchain/src/IOptimizer.sol @@ -10,6 +10,14 @@ struct OptimizerInput { int256 shift; } +/// @dev Safe bear-mode defaults shared by Optimizer._bearDefaults() and +/// LiquidityManager.recenter()'s catch block. Keep all four here so +/// the two call-sites cannot silently diverge. +uint256 constant BEAR_CAPITAL_INEFFICIENCY = 0; +uint256 constant BEAR_ANCHOR_SHARE = 3e17; +uint24 constant BEAR_ANCHOR_WIDTH = 100; +uint256 constant BEAR_DISCOVERY_DEPTH = 3e17; + /** * @title IOptimizer * @notice Minimal interface for the Optimizer contract consumed by LiquidityManager. diff --git a/onchain/src/LiquidityManager.sol b/onchain/src/LiquidityManager.sol index 92ce730..084655b 100644 --- a/onchain/src/LiquidityManager.sol +++ b/onchain/src/LiquidityManager.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.19; import { Kraiken } from "./Kraiken.sol"; -import { IOptimizer } from "./IOptimizer.sol"; +import { IOptimizer, BEAR_CAPITAL_INEFFICIENCY, BEAR_ANCHOR_SHARE, BEAR_ANCHOR_WIDTH, BEAR_DISCOVERY_DEPTH } from "./IOptimizer.sol"; import { PriceOracle } from "./abstracts/PriceOracle.sol"; import { ThreePositionStrategy } from "./abstracts/ThreePositionStrategy.sol"; import { IWETH9 } from "./interfaces/IWETH9.sol"; @@ -234,10 +234,10 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle { } catch { // Fallback to safe bear-mode defaults if optimizer fails PositionParams memory defaultParams = PositionParams({ - capitalInefficiency: 0, // CI=0 proven safest - anchorShare: 3e17, // 30% — defensive floor allocation - anchorWidth: 100, // Max width — avoids AW 30-90 kill zone - discoveryDepth: 3e17 // 0.3e18 + capitalInefficiency: BEAR_CAPITAL_INEFFICIENCY, + anchorShare: BEAR_ANCHOR_SHARE, + anchorWidth: BEAR_ANCHOR_WIDTH, + discoveryDepth: BEAR_DISCOVERY_DEPTH }); _setPositions(currentTick, defaultParams); diff --git a/onchain/src/Optimizer.sol b/onchain/src/Optimizer.sol index ad48d2b..7c596e7 100644 --- a/onchain/src/Optimizer.sol +++ b/onchain/src/Optimizer.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; -import { IOptimizer, OptimizerInput } from "./IOptimizer.sol"; +import { IOptimizer, OptimizerInput, BEAR_CAPITAL_INEFFICIENCY, BEAR_ANCHOR_SHARE, BEAR_ANCHOR_WIDTH, BEAR_DISCOVERY_DEPTH } from "./IOptimizer.sol"; import { Kraiken } from "./Kraiken.sol"; import { Stake } from "./Stake.sol"; @@ -212,12 +212,10 @@ contract Optimizer is Initializable, UUPSUpgradeable, IOptimizer { /** * @notice Safe bear-mode defaults returned when calculateParams exceeds its * gas budget or reverts. - * @dev Values must stay in sync with the catch block in LiquidityManager.recenter() - * ({capitalInefficiency:0, anchorShare:3e17, anchorWidth:100, discoveryDepth:3e17}). - * Update both locations together if the safe defaults ever change. + * @dev Constants defined in IOptimizer.sol, shared with LiquidityManager.recenter(). */ function _bearDefaults() internal pure returns (uint256 capitalInefficiency, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth) { - return (0, 3e17, 100, 3e17); + return (BEAR_CAPITAL_INEFFICIENCY, BEAR_ANCHOR_SHARE, BEAR_ANCHOR_WIDTH, BEAR_DISCOVERY_DEPTH); } // ---- Normalization helpers ----