2024-03-18 12:42:30 +01:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
2024-03-28 19:55:01 +01:00
|
|
|
pragma solidity ^0.8.19;
|
2024-03-18 12:42:30 +01:00
|
|
|
|
2025-10-04 15:17:09 +02:00
|
|
|
import { Kraiken } from "./Kraiken.sol";
|
|
|
|
|
import { Optimizer } from "./Optimizer.sol";
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
import { PriceOracle } from "./abstracts/PriceOracle.sol";
|
|
|
|
|
import { ThreePositionStrategy } from "./abstracts/ThreePositionStrategy.sol";
|
|
|
|
|
import { IWETH9 } from "./interfaces/IWETH9.sol";
|
|
|
|
|
import { CallbackValidation } from "@aperture/uni-v3-lib/CallbackValidation.sol";
|
|
|
|
|
import { PoolAddress, PoolKey } from "@aperture/uni-v3-lib/PoolAddress.sol";
|
|
|
|
|
import { IERC20 } from "@openzeppelin/token/ERC20/IERC20.sol";
|
|
|
|
|
import { SafeERC20 } from "@openzeppelin/token/ERC20/utils/SafeERC20.sol";
|
|
|
|
|
import { IUniswapV3Pool } from "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
|
|
|
|
import { PositionKey } from "@uniswap-v3-periphery/libraries/PositionKey.sol";
|
2024-03-28 21:50:22 +01:00
|
|
|
|
2024-03-18 12:42:30 +01:00
|
|
|
/**
|
2025-07-18 19:37:30 +02:00
|
|
|
* @title LiquidityManager
|
|
|
|
|
* @notice Manages liquidity provisioning on Uniswap V3 using the three-position anti-arbitrage strategy
|
|
|
|
|
* @dev Inherits from modular contracts for better separation of concerns and testability
|
2025-10-04 15:17:09 +02:00
|
|
|
*
|
2025-08-18 00:16:09 +02:00
|
|
|
* Key features:
|
|
|
|
|
* - Three-position anti-arbitrage strategy (ANCHOR, DISCOVERY, FLOOR)
|
|
|
|
|
* - Dynamic parameter adjustment via Optimizer contract
|
|
|
|
|
* - Asymmetric slippage profile prevents profitable arbitrage
|
|
|
|
|
* - Exclusive minting rights for KRAIKEN token
|
2025-10-04 15:17:09 +02:00
|
|
|
*
|
2025-08-18 00:16:09 +02:00
|
|
|
* Price Validation:
|
|
|
|
|
* - 5-minute TWAP with 50-tick tolerance
|
|
|
|
|
* - Prevents oracle manipulation attacks
|
2024-07-13 18:33:47 +02:00
|
|
|
*/
|
2025-07-18 19:37:30 +02:00
|
|
|
contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
using SafeERC20 for IERC20;
|
|
|
|
|
|
2025-08-18 00:16:09 +02:00
|
|
|
/// @notice Uniswap V3 fee tier (1%) - 10,000 basis points
|
2024-07-09 18:00:39 +02:00
|
|
|
uint24 internal constant FEE = uint24(10_000);
|
2024-07-16 19:47:39 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Immutable contract references
|
2024-07-13 14:56:13 +02:00
|
|
|
address private immutable factory;
|
|
|
|
|
IWETH9 private immutable weth;
|
2025-08-19 11:05:08 +02:00
|
|
|
Kraiken private immutable kraiken;
|
2025-02-01 21:49:15 +01:00
|
|
|
Optimizer private immutable optimizer;
|
2024-07-13 14:56:13 +02:00
|
|
|
IUniswapV3Pool private immutable pool;
|
|
|
|
|
bool private immutable token0isWeth;
|
2024-07-09 18:00:39 +02:00
|
|
|
PoolKey private poolKey;
|
2024-03-18 12:42:30 +01:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Access control and fee management
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
address private immutable deployer;
|
2025-10-04 15:40:30 +02:00
|
|
|
address public recenterAccess;
|
2024-07-09 18:00:39 +02:00
|
|
|
address public feeDestination;
|
2026-03-12 16:13:44 +00:00
|
|
|
bool public feeDestinationLocked;
|
2024-03-18 12:42:30 +01:00
|
|
|
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
/// @notice Last recenter tick — used to determine net trade direction between recenters
|
|
|
|
|
int24 public lastRecenterTick;
|
|
|
|
|
|
2026-03-12 08:50:07 +00:00
|
|
|
/// @notice Last recenter timestamp — rate limits open recenters.
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
uint256 public lastRecenterTime;
|
|
|
|
|
/// @notice Minimum seconds between open recenters (when recenterAccess is unset)
|
|
|
|
|
uint256 internal constant MIN_RECENTER_INTERVAL = 60;
|
2026-03-11 10:02:47 +00:00
|
|
|
/// @notice Target observation cardinality requested from the pool during construction
|
|
|
|
|
uint16 internal constant ORACLE_CARDINALITY = 100;
|
2026-03-11 08:17:49 +00:00
|
|
|
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
/// @notice Emitted on each successful recenter for monitoring and indexing
|
|
|
|
|
event Recentered(int24 indexed currentTick, bool indexed isUp);
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Custom errors
|
2024-07-13 14:56:13 +02:00
|
|
|
error ZeroAddressInSetter();
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Access control modifier
|
2024-07-16 19:47:39 +02:00
|
|
|
modifier onlyFeeDestination() {
|
|
|
|
|
require(msg.sender == address(feeDestination), "only callable by feeDestination");
|
|
|
|
|
_;
|
|
|
|
|
}
|
2024-03-18 12:42:30 +01:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Constructor initializes all contract references and pool configuration
|
|
|
|
|
/// @param _factory The address of the Uniswap V3 factory
|
|
|
|
|
/// @param _WETH9 The address of the WETH contract
|
2025-08-19 11:05:08 +02:00
|
|
|
/// @param _kraiken The address of the Kraiken token contract
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @param _optimizer The address of the optimizer contract
|
2025-08-19 11:05:08 +02:00
|
|
|
constructor(address _factory, address _WETH9, address _kraiken, address _optimizer) {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
deployer = msg.sender;
|
2024-03-18 12:42:30 +01:00
|
|
|
factory = _factory;
|
|
|
|
|
weth = IWETH9(_WETH9);
|
2025-08-19 11:05:08 +02:00
|
|
|
poolKey = PoolAddress.getPoolKey(_WETH9, _kraiken, FEE);
|
2024-03-18 12:42:30 +01:00
|
|
|
pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
|
2025-08-19 11:05:08 +02:00
|
|
|
kraiken = Kraiken(_kraiken);
|
|
|
|
|
token0isWeth = _WETH9 < _kraiken;
|
2025-07-08 10:31:41 +02:00
|
|
|
optimizer = Optimizer(_optimizer);
|
2026-03-11 08:17:49 +00:00
|
|
|
// Increase observation cardinality so pool.observe() has sufficient history
|
2026-03-12 08:50:07 +00:00
|
|
|
// for _isPriceStable() TWAP checks.
|
2026-03-11 10:02:47 +00:00
|
|
|
pool.increaseObservationCardinalityNext(ORACLE_CARDINALITY);
|
2024-03-18 12:42:30 +01:00
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Callback function for Uniswap V3 mint operations
|
|
|
|
|
/// @param amount0Owed Amount of token0 owed for the liquidity provision
|
|
|
|
|
/// @param amount1Owed Amount of token1 owed for the liquidity provision
|
2024-03-18 12:42:30 +01:00
|
|
|
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
|
|
|
|
|
CallbackValidation.verifyCallback(factory, poolKey);
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2026-02-04 16:20:57 +00:00
|
|
|
// Handle KRAIKEN minting - use existing balance first, then mint only the difference
|
2025-08-19 11:05:08 +02:00
|
|
|
uint256 kraikenPulled = token0isWeth ? amount1Owed : amount0Owed;
|
2026-02-04 16:20:57 +00:00
|
|
|
uint256 kraikenBalance = kraiken.balanceOf(address(this));
|
|
|
|
|
if (kraikenBalance < kraikenPulled) {
|
|
|
|
|
kraiken.mint(kraikenPulled - kraikenBalance);
|
|
|
|
|
}
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Handle WETH conversion
|
2024-04-28 07:00:53 +02:00
|
|
|
uint256 ethOwed = token0isWeth ? amount0Owed : amount1Owed;
|
|
|
|
|
if (weth.balanceOf(address(this)) < ethOwed) {
|
2025-10-04 15:17:09 +02:00
|
|
|
weth.deposit{ value: address(this).balance }();
|
2024-04-28 07:00:53 +02:00
|
|
|
}
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Transfer tokens to pool
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
if (amount0Owed > 0) IERC20(poolKey.token0).safeTransfer(msg.sender, amount0Owed);
|
|
|
|
|
if (amount1Owed > 0) IERC20(poolKey.token1).safeTransfer(msg.sender, amount1Owed);
|
2024-03-18 12:42:30 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-12 16:13:44 +00:00
|
|
|
/// @notice Sets the fee destination address (deployer only)
|
|
|
|
|
/// @dev Any EOA can be set repeatedly. Once a contract address is set, locks permanently.
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @param feeDestination_ The address that will receive trading fees
|
2024-06-09 16:06:41 +02:00
|
|
|
function setFeeDestination(address feeDestination_) external {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
require(msg.sender == deployer, "only deployer");
|
2024-07-13 14:56:13 +02:00
|
|
|
if (address(0) == feeDestination_) revert ZeroAddressInSetter();
|
2026-03-12 16:13:44 +00:00
|
|
|
require(!feeDestinationLocked, "fee destination locked");
|
2024-06-09 16:06:41 +02:00
|
|
|
feeDestination = feeDestination_;
|
2026-03-12 16:13:44 +00:00
|
|
|
if (feeDestination_.code.length > 0) {
|
|
|
|
|
feeDestinationLocked = true;
|
|
|
|
|
}
|
2024-06-09 16:06:41 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Sets recenter access for testing/emergency purposes
|
|
|
|
|
/// @param addr Address to grant recenter access
|
2024-09-12 17:00:24 +02:00
|
|
|
function setRecenterAccess(address addr) external onlyFeeDestination {
|
|
|
|
|
recenterAccess = addr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Revokes recenter access
|
2024-09-12 17:00:24 +02:00
|
|
|
function revokeRecenterAccess() external onlyFeeDestination {
|
|
|
|
|
recenterAccess = address(0);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Adjusts liquidity positions in response to price movements
|
|
|
|
|
/// @return isUp True if price moved up (relative to token ordering)
|
|
|
|
|
function recenter() external returns (bool isUp) {
|
|
|
|
|
(, int24 currentTick,,,,,) = pool.slot0();
|
2025-07-06 10:08:59 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Validate access and price stability
|
|
|
|
|
if (recenterAccess != address(0)) {
|
|
|
|
|
require(msg.sender == recenterAccess, "access denied");
|
2024-04-11 07:28:54 +02:00
|
|
|
} else {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
require(block.timestamp >= lastRecenterTime + MIN_RECENTER_INTERVAL, "recenter cooldown");
|
2025-07-18 19:37:30 +02:00
|
|
|
require(_isPriceStable(currentTick), "price deviated from oracle");
|
2024-04-11 07:28:54 +02:00
|
|
|
}
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
lastRecenterTime = block.timestamp;
|
2024-03-28 21:50:22 +01:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Check if price movement is sufficient for recentering
|
|
|
|
|
isUp = false;
|
|
|
|
|
if (positions[Stage.ANCHOR].liquidity > 0) {
|
|
|
|
|
int24 anchorTickLower = positions[Stage.ANCHOR].tickLower;
|
|
|
|
|
int24 anchorTickUpper = positions[Stage.ANCHOR].tickUpper;
|
2025-07-25 10:52:56 +02:00
|
|
|
int24 centerTick = anchorTickLower + (anchorTickUpper - anchorTickLower) / 2;
|
2024-08-15 15:17:44 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
bool isEnough;
|
|
|
|
|
(isUp, isEnough) = _validatePriceMovement(currentTick, centerTick, TICK_SPACING, token0isWeth);
|
|
|
|
|
require(isEnough, "amplitude not reached.");
|
2024-08-15 15:17:44 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Remove all existing positions and collect fees
|
2026-03-11 03:31:45 +00:00
|
|
|
// Pass tick direction to determine if VWAP should record.
|
|
|
|
|
// CRITICAL: record VWAP only when price FALLS (sells / ETH outflow), never when it rises.
|
|
|
|
|
// If we recorded during buy events, an adversary could run N buy-recenter cycles to push
|
|
|
|
|
// VWAP upward toward the inflated price. When VWAP ≈ current tick, mirrorTick ≈ currentTick,
|
|
|
|
|
// so the floor is placed near the inflated price — crystallising IL when the adversary sells.
|
|
|
|
|
// Freezing VWAP during buy-only cycles keeps the floor anchored to the historical baseline.
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
bool shouldRecordVWAP;
|
|
|
|
|
if (cumulativeVolume == 0) {
|
|
|
|
|
// No VWAP data yet — always bootstrap to prevent vwapX96=0 fallback
|
|
|
|
|
shouldRecordVWAP = true;
|
|
|
|
|
} else if (lastRecenterTick != 0) {
|
2026-03-11 03:31:45 +00:00
|
|
|
// token0isWeth: tick UP = price down in KRK terms = sells = ETH outflow
|
|
|
|
|
// !token0isWeth: tick DOWN = price down in KRK terms = sells = ETH outflow
|
|
|
|
|
// Only record when price falls — VWAP stays anchored to historical levels during buy attacks.
|
|
|
|
|
shouldRecordVWAP = token0isWeth ? (currentTick > lastRecenterTick) : (currentTick < lastRecenterTick);
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
} else {
|
|
|
|
|
// First recenter — no reference point, record conservatively
|
|
|
|
|
shouldRecordVWAP = true;
|
|
|
|
|
}
|
|
|
|
|
lastRecenterTick = currentTick;
|
|
|
|
|
|
2026-03-12 08:50:07 +00:00
|
|
|
_scrapePositions(shouldRecordVWAP, currentTick);
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Update total supply tracking if price moved up
|
|
|
|
|
if (isUp) {
|
2025-08-19 11:05:08 +02:00
|
|
|
kraiken.setPreviousTotalSupply(kraiken.totalSupply());
|
2024-08-15 15:17:44 +02:00
|
|
|
}
|
2025-07-08 10:31:41 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Get optimizer parameters and set new positions
|
2025-10-04 15:17:09 +02:00
|
|
|
try optimizer.getLiquidityParams() returns (uint256 capitalInefficiency, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth) {
|
2025-07-18 19:37:30 +02:00
|
|
|
// Clamp parameters to valid ranges
|
|
|
|
|
PositionParams memory params = PositionParams({
|
|
|
|
|
capitalInefficiency: (capitalInefficiency > 10 ** 18) ? 10 ** 18 : capitalInefficiency,
|
|
|
|
|
anchorShare: (anchorShare > 10 ** 18) ? 10 ** 18 : anchorShare,
|
|
|
|
|
anchorWidth: (anchorWidth > 100) ? 100 : anchorWidth,
|
|
|
|
|
discoveryDepth: (discoveryDepth > 10 ** 18) ? 10 ** 18 : discoveryDepth
|
|
|
|
|
});
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
_setPositions(currentTick, params);
|
|
|
|
|
} catch {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
// Fallback to safe bear-mode defaults if optimizer fails
|
2025-07-18 19:37:30 +02:00
|
|
|
PositionParams memory defaultParams = PositionParams({
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
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
|
2025-10-04 15:17:09 +02:00
|
|
|
});
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
_setPositions(currentTick, defaultParams);
|
2024-07-06 18:36:13 +02:00
|
|
|
}
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
|
|
|
|
|
emit Recentered(currentTick, isUp);
|
2024-07-18 16:50:23 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Removes all positions and collects fees
|
2026-03-11 04:11:02 +00:00
|
|
|
/// @param recordVWAP Whether to record VWAP (only when net ETH outflow / price fell since last recenter, or at bootstrap)
|
2026-03-12 08:50:07 +00:00
|
|
|
/// @param currentTick The current pool tick at time of recenter, used as the VWAP price sample
|
|
|
|
|
function _scrapePositions(bool recordVWAP, int24 currentTick) internal {
|
2024-06-09 16:06:41 +02:00
|
|
|
uint256 fee0 = 0;
|
|
|
|
|
uint256 fee1 = 0;
|
2026-03-12 08:50:07 +00:00
|
|
|
// Price at current tick: volume-weighted, sampled once per recenter.
|
|
|
|
|
// token0isWeth: tick represents KRK/ETH — negate for price in ETH per KRK terms.
|
|
|
|
|
uint256 currentPrice = _priceAtTick(token0isWeth ? -1 * currentTick : currentTick);
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2025-07-08 10:31:41 +02:00
|
|
|
for (uint256 i = uint256(Stage.FLOOR); i <= uint256(Stage.DISCOVERY); i++) {
|
2024-06-09 16:06:41 +02:00
|
|
|
TokenPosition storage position = positions[Stage(i)];
|
|
|
|
|
if (position.liquidity > 0) {
|
2025-07-18 19:37:30 +02:00
|
|
|
// Burn liquidity and collect tokens + fees
|
2025-10-04 15:17:09 +02:00
|
|
|
(uint256 amount0, uint256 amount1) = pool.burn(position.tickLower, position.tickUpper, position.liquidity);
|
|
|
|
|
|
|
|
|
|
(uint256 collected0, uint256 collected1) =
|
|
|
|
|
pool.collect(address(this), position.tickLower, position.tickUpper, type(uint128).max, type(uint128).max);
|
2025-07-18 19:37:30 +02:00
|
|
|
|
|
|
|
|
// Calculate fees
|
2024-06-09 16:06:41 +02:00
|
|
|
fee0 += collected0 - amount0;
|
|
|
|
|
fee1 += collected1 - amount1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-06 18:36:13 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// Transfer fees and record volume for VWAP
|
2026-03-11 04:11:02 +00:00
|
|
|
// VWAP is recorded only on sell events (price fell) or at bootstrap — see recenter().
|
2026-03-10 10:11:41 +00:00
|
|
|
// Skip transfer when feeDestination is self — fees accrue as deployable liquidity.
|
|
|
|
|
if (feeDestination != address(this)) {
|
|
|
|
|
if (fee0 > 0) {
|
|
|
|
|
if (token0isWeth) {
|
|
|
|
|
IERC20(address(weth)).safeTransfer(feeDestination, fee0);
|
|
|
|
|
} else {
|
|
|
|
|
IERC20(address(kraiken)).safeTransfer(feeDestination, fee0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (fee1 > 0) {
|
|
|
|
|
if (token0isWeth) {
|
|
|
|
|
IERC20(address(kraiken)).safeTransfer(feeDestination, fee1);
|
|
|
|
|
} else {
|
|
|
|
|
IERC20(address(weth)).safeTransfer(feeDestination, fee1);
|
|
|
|
|
}
|
2024-07-06 18:36:13 +02:00
|
|
|
}
|
2024-06-09 16:06:41 +02:00
|
|
|
}
|
2025-10-04 15:17:09 +02:00
|
|
|
|
2026-03-10 10:11:41 +00:00
|
|
|
// Always record VWAP regardless of fee destination
|
|
|
|
|
if (recordVWAP) {
|
|
|
|
|
uint256 ethFee = token0isWeth ? fee0 : fee1;
|
|
|
|
|
if (ethFee > 0) _recordVolumeAndPrice(currentPrice, ethFee);
|
2024-06-09 16:06:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Allow contract to receive ETH
|
2025-10-04 15:17:09 +02:00
|
|
|
receive() external payable { }
|
2024-06-07 11:22:22 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
// ========================================
|
|
|
|
|
// ABSTRACT FUNCTION IMPLEMENTATIONS
|
|
|
|
|
// ========================================
|
2024-07-09 18:00:39 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from PriceOracle
|
|
|
|
|
function _getPool() internal view override returns (IUniswapV3Pool) {
|
|
|
|
|
return pool;
|
2024-06-07 11:22:22 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
2025-08-19 11:05:08 +02:00
|
|
|
function _getKraikenToken() internal view override returns (address) {
|
|
|
|
|
return address(kraiken);
|
2025-07-18 19:37:30 +02:00
|
|
|
}
|
2024-04-03 21:43:12 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
|
|
|
|
function _getWethToken() internal view override returns (address) {
|
|
|
|
|
return address(weth);
|
|
|
|
|
}
|
2024-06-09 16:06:41 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
|
|
|
|
function _isToken0Weth() internal view override returns (bool) {
|
|
|
|
|
return token0isWeth;
|
|
|
|
|
}
|
2024-04-03 21:43:12 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
|
|
|
|
function _mintPosition(Stage stage, int24 tickLower, int24 tickUpper, uint128 liquidity) internal override {
|
|
|
|
|
pool.mint(address(this), tickLower, tickUpper, liquidity, abi.encode(poolKey));
|
2025-10-04 15:17:09 +02:00
|
|
|
positions[stage] = TokenPosition({ liquidity: liquidity, tickLower: tickLower, tickUpper: tickUpper });
|
2025-07-18 19:37:30 +02:00
|
|
|
}
|
2024-04-03 21:43:12 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
|
|
|
|
function _getEthBalance() internal view override returns (uint256) {
|
|
|
|
|
return address(this).balance + weth.balanceOf(address(this));
|
|
|
|
|
}
|
2024-04-03 21:43:12 +02:00
|
|
|
|
2025-07-18 19:37:30 +02:00
|
|
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
/// @dev Subtracts KRK at feeDestination (protocol revenue) and stakingPool (locked in staking)
|
|
|
|
|
/// since neither can be sold into the floor — only trader-held KRK matters for scarcity
|
2025-07-18 19:37:30 +02:00
|
|
|
function _getOutstandingSupply() internal view override returns (uint256) {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
uint256 supply = kraiken.outstandingSupply();
|
2026-03-10 10:11:41 +00:00
|
|
|
// Skip subtraction when feeDestination is self: outstandingSupply() already
|
|
|
|
|
// excludes kraiken.balanceOf(address(this)), so subtracting again would double-count.
|
|
|
|
|
if (feeDestination != address(0) && feeDestination != address(this)) {
|
feat: OptimizerV3 with direct 2D staking-to-LP parameter mapping
Core protocol changes for launch readiness:
- OptimizerV3: binary bear/bull mapping from (staking%, avgTax) — avoids
exploitable AW 30-90 kill zone. Bear: AS=30%, AW=100, CI=0, DD=0.3e18.
Bull: AS=100%, AW=20, CI=0, DD=1e18. UUPS upgradeable with __gap[48].
- Directional VWAP: only records prices on ETH inflow (buys), preventing
sell-side dilution of price memory
- Floor formula: unified max(scarcity, mirror, clamp) — VWAP mirror uses
distance from adjusted VWAP as floor distance, no branching
- PriceOracle (M-1 fix): correct fallback TWAP divisor (60000s, not 300s)
- Access control (M-2 fix): deployer-only guard on one-time setters
- Recenter rate limit (M-3 fix): 60-second cooldown for open recenters
- Safe fallback params: recenter() optimizer-failure defaults changed from
exploitable CI=50%/AW=50 to safe bear-mode CI=0/AW=100
- Recentered event for monitoring and indexing
- VERSION bump to 2, kraiken-lib COMPATIBLE_CONTRACT_VERSIONS updated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:21:18 +00:00
|
|
|
supply -= kraiken.balanceOf(feeDestination);
|
|
|
|
|
}
|
|
|
|
|
(, address stakingPoolAddr) = kraiken.peripheryContracts();
|
|
|
|
|
if (stakingPoolAddr != address(0)) {
|
|
|
|
|
supply -= kraiken.balanceOf(stakingPoolAddr);
|
|
|
|
|
}
|
|
|
|
|
return supply;
|
2024-03-18 12:42:30 +01:00
|
|
|
}
|
2025-10-04 15:17:09 +02:00
|
|
|
}
|