// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import {Optimizer} from "./Optimizer.sol"; import {OptimizerV3Push3} from "./OptimizerV3Push3.sol"; import {OptimizerInput} from "./IOptimizer.sol"; /** * @title OptimizerV3 * @notice UUPS-upgradeable Optimizer that uses the transpiled Push3 calculateParams logic. * * @dev This contract extends the base Optimizer and overrides calculateParams to delegate * to the transpiled OptimizerV3Push3 implementation using delegatecall. It maintains * full storage layout compatibility for UUPS upgrades. * * Storage layout (inherited from Optimizer): * - Initializable slots * - UUPSUpgradeable slots (admin address in ERC1967 storage) * - kraiken (Kraiken) * - stake (Stake) * - vwapTracker (address) * - pool (address) * - lastRecenterTimestamp (uint256) * - recenterRecorder (address) */ contract OptimizerV3 is Optimizer { /** * @notice Override calculateParams to use the transpiled Push3 logic. * @dev This creates a temporary OptimizerV3Push3 instance for each call. * While not gas-optimal, it maintains purity and allows us to use * the transpiled code without storage layout concerns. * * @param inputs 8 dyadic rational slots (same interface as base Optimizer) * @return capitalInefficiency Capital buffer level (0..1e18) * @return anchorShare Fraction of non-floor ETH in anchor (0..1e18) * @return anchorWidth Anchor position width in tick units (uint24) * @return discoveryDepth Discovery liquidity density (0..1e18) */ function calculateParams(OptimizerInput[8] memory inputs) public pure override returns (uint256 capitalInefficiency, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth) { // Inline the Push3 implementation to preserve purity // This is auto-generated from optimizer_v3.push3 via the transpiler // Validate mantissa for percentageStaked require(inputs[0].mantissa <= 1e18, "mantissa overflow"); // Validate that shift is 0 (future-only field, not yet supported) for (uint256 k = 0; k < 8; k++) { require(inputs[k].shift == 0, "shift not yet supported"); } uint256 percentagestaked = uint256(uint256(inputs[0].mantissa)); uint256 taxrate = uint256(uint256(inputs[1].mantissa)); uint256 staked = uint256(((percentagestaked * 100) / 1000000000000000000)); uint256 r37; uint256 r38; uint256 r39; uint256 r40; if ((staked > 91)) { uint256 deltas = uint256((100 - staked)); // Tax rate index calculation (deep nested if-else chain) uint256 r28; if ((taxrate <= 206185567010309)) { r28 = 0; } else if ((taxrate <= 412371134020618)) { r28 = 1; } else if ((taxrate <= 618556701030927)) { r28 = 2; } else if ((taxrate <= 1030927835051546)) { r28 = 3; } else if ((taxrate <= 1546391752577319)) { r28 = 4; } else if ((taxrate <= 2164948453608247)) { r28 = 5; } else if ((taxrate <= 2783505154639175)) { r28 = 6; } else if ((taxrate <= 3608247422680412)) { r28 = 7; } else if ((taxrate <= 4639175257731958)) { r28 = 8; } else if ((taxrate <= 5670103092783505)) { r28 = 9; } else if ((taxrate <= 7216494845360824)) { r28 = 10; } else if ((taxrate <= 9278350515463917)) { r28 = 11; } else if ((taxrate <= 11855670103092783)) { r28 = 12; } else if ((taxrate <= 15979381443298969)) { r28 = 13; } else if ((taxrate <= 22164948453608247)) { r28 = 14; } else if ((taxrate <= 29381443298969072)) { r28 = 15; } else if ((taxrate <= 38144329896907216)) { r28 = 16; } else if ((taxrate <= 49484536082474226)) { r28 = 17; } else if ((taxrate <= 63917525773195876)) { r28 = 18; } else if ((taxrate <= 83505154639175257)) { r28 = 19; } else if ((taxrate <= 109278350515463917)) { r28 = 20; } else if ((taxrate <= 144329896907216494)) { r28 = 21; } else if ((taxrate <= 185567010309278350)) { r28 = 22; } else if ((taxrate <= 237113402061855670)) { r28 = 23; } else if ((taxrate <= 309278350515463917)) { r28 = 24; } else if ((taxrate <= 402061855670103092)) { r28 = 25; } else if ((taxrate <= 520618556701030927)) { r28 = 26; } else if ((taxrate <= 680412371134020618)) { r28 = 27; } else if ((taxrate <= 886597938144329896)) { r28 = 28; } else { r28 = 29; } uint256 dup29 = r28; uint256 r32; if ((dup29 >= 14)) { uint256 dup30 = (dup29 + 1); r32 = (dup30 > 29) ? 29 : dup30; } else { r32 = dup29; } uint256 effidx = r32; // Bull/bear decision based on penalty if ((((((deltas * deltas) * deltas) * effidx) / 20) < 50)) { // Bull r37 = 1000000000000000000; // AS = 1e18 r38 = 20; // AW = 20 r39 = 1000000000000000000; // DD = 1e18 r40 = 0; // CI = 0 } else { // Bear r37 = 300000000000000000; // AS = 0.3e18 r38 = 100; // AW = 100 r39 = 300000000000000000; // DD = 0.3e18 r40 = 0; // CI = 0 } } else { // Bear (staked <= 91%) r37 = 300000000000000000; r38 = 100; r39 = 300000000000000000; r40 = 0; } anchorShare = r37; anchorWidth = uint24(r38); discoveryDepth = r39; capitalInefficiency = r40; } }