// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import { MockToken } from "./MockToken.sol"; /** * @title BacktestKraiken * @notice Kraiken-compatible ERC-20 for backtesting purposes only. * * Dual mint interface: * - MockToken.mint(address to, uint256 amount) — public, inherited from MockToken. * Used by EventReplayer to seed historical pool positions without access checks. * - mint(uint256 amount) — restricted to liquidityManager. * Mirrors Kraiken.mint(uint256) so LiquidityManager operates unchanged. * * burn(uint256), setPreviousTotalSupply(), outstandingSupply(), and peripheryContracts() * mirror the real Kraiken interface that LiquidityManager depends on. * * Omissions vs real Kraiken (acceptable for backtesting): * - No staking pool proportional minting (no Stake.sol deployed). * - No ERC20Permit extension. * - setLiquidityManager() has no deployer-only guard (script context only). */ contract BacktestKraiken is MockToken { address public liquidityManager; uint256 public previousTotalSupply; constructor() MockToken("Backtesting KRK", "bKRK", 18) { } modifier onlyLiquidityManager() { require(msg.sender == liquidityManager, "only liquidity manager"); _; } // ------------------------------------------------------------------------- // Wiring // ------------------------------------------------------------------------- /** * @notice Wire the LiquidityManager. Can only be called once. */ function setLiquidityManager(address lm) external { require(liquidityManager == address(0), "already set"); liquidityManager = lm; } // ------------------------------------------------------------------------- // LM-restricted supply management (mirrors Kraiken interface) // ------------------------------------------------------------------------- /** * @notice Mint `amount` tokens to the LiquidityManager. * Overloads MockToken.mint(address,uint256) — the two signatures * have distinct ABI selectors and coexist without conflict. */ function mint(uint256 amount) external onlyLiquidityManager { if (amount > 0) _mint(liquidityManager, amount); if (previousTotalSupply == 0) previousTotalSupply = totalSupply(); } /** * @notice Burn `amount` tokens from the LiquidityManager's balance. */ function burn(uint256 amount) external onlyLiquidityManager { if (amount > 0) _burn(liquidityManager, amount); } /** * @notice Called by LM when isUp == true during recenter. */ function setPreviousTotalSupply(uint256 ts) external onlyLiquidityManager { previousTotalSupply = ts; } // ------------------------------------------------------------------------- // View helpers (mirrors Kraiken interface) // ------------------------------------------------------------------------- /** * @notice Total supply minus the LM's own balance (trader-held supply). */ function outstandingSupply() external view returns (uint256) { return totalSupply() - balanceOf(liquidityManager); } /** * @notice Returns (liquidityManager, address(0)) — no staking pool in backtests. * LiquidityManager._getOutstandingSupply() calls this to exclude staked KRK; * returning address(0) for stakingPool skips that subtraction safely. */ function peripheryContracts() external view returns (address, address) { return (liquidityManager, address(0)); } }