// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import { LiquidityManager } from "../../src/LiquidityManager.sol"; import { OptimizerV3Push3 } from "../../src/OptimizerV3Push3.sol"; import { BacktestKraiken } from "./BacktestKraiken.sol"; import { MockToken } from "./MockToken.sol"; /** * @notice Deployment result for the KrAIken system on the shadow pool. */ struct KrAIkenSystem { BacktestKraiken kraiken; /// @dev OptimizerV3Push3 is used as the optimizer address. Its getLiquidityParams() /// uses zeroed inputs (no on-chain stake data) and returns bear-mode defaults on /// every recenter. This is intentional for backtesting. OptimizerV3Push3 optimizer; LiquidityManager lm; } /** * @title KrAIkenDeployer * @notice Library that deploys the KrAIken protocol contracts on top of a shadow pool * for backtesting purposes. * * Deployment order follows DeployLocal.sol: * 1. Deploy OptimizerV3Push3 (no proxy — it only exposes isBullMarket(), so LM falls * back to bear-mode defaults via try/catch on every recenter call). * 2. Deploy LiquidityManager pointing at the shadow factory + mock WETH + BacktestKraiken. * 3. Wire BacktestKraiken → LM (setLiquidityManager). * 4. Set fee destination on LM. * 5. Fund LM with mock WETH (initial capital). * * @dev All functions are `internal` so they are inlined into BacktestRunner.s.sol, * keeping msg.sender consistent with the broadcaster throughout deployment. */ library KrAIkenDeployer { uint256 internal constant DEFAULT_INITIAL_CAPITAL = 10 ether; /** * @notice Deploy the KrAIken system with default initial capital (10 ETH equivalent). */ function deploy(address shadowFactory, address mockWeth, address krkToken, address feeDestination) internal returns (KrAIkenSystem memory sys) { return deploy(shadowFactory, mockWeth, krkToken, feeDestination, DEFAULT_INITIAL_CAPITAL); } /** * @notice Deploy the KrAIken system with configurable initial capital. * * @param shadowFactory Factory that created the shadow pool. * @param mockWeth Mock WETH token address (18-decimal ERC-20, freely mintable). * @param krkToken BacktestKraiken token address (setLiquidityManager not yet called). * @param feeDestination Address that will receive LP fees; also used as the caller * for subsequent setRecenterAccess() calls. * @param initialCapital Mock WETH minted to LM so recenter() has capital to deploy. */ function deploy( address shadowFactory, address mockWeth, address krkToken, address feeDestination, uint256 initialCapital ) internal returns (KrAIkenSystem memory sys) { // 1. Deploy OptimizerV3Push3. // OptimizerV3Push3.getLiquidityParams() uses zeroed inputs (no stake data), // so every recenter uses bear defaults — conservative and correct for a // baseline backtest. OptimizerV3Push3 optimizer = new OptimizerV3Push3(); // 2. Deploy LiquidityManager. It computes the pool address from factory + WETH + // KRK + FEE (10 000). The shadow pool must have been created with the same // factory and the same fee tier (ShadowPoolDeployer.SHADOW_FEE == 10 000). LiquidityManager lm = new LiquidityManager(shadowFactory, mockWeth, krkToken, address(optimizer)); // 3. Wire BacktestKraiken → LM so the restricted mint/burn functions work. BacktestKraiken(krkToken).setLiquidityManager(address(lm)); // 4. Set fee destination (required before setRecenterAccess can be called). lm.setFeeDestination(feeDestination); // 5. Fund LM with mock WETH. recenter() uses _getEthBalance() which reads // weth.balanceOf(address(this)). Pre-funding avoids calling weth.deposit() // (which MockToken does not implement). MockToken(mockWeth).mint(address(lm), initialCapital); sys = KrAIkenSystem({ kraiken: BacktestKraiken(krkToken), optimizer: optimizer, lm: lm }); } }