From f844f765334aa0d05ee30ca9ab73337ddaaa0404 Mon Sep 17 00:00:00 2001 From: openhands Date: Thu, 12 Mar 2026 09:04:52 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20OptimizerV3=20=E2=80=94=20use=20canonica?= =?UTF-8?q?l=20transpiler=20output,=20fix=20register=20mapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review bot caught r37/r39 inversion (anchorShare ↔ discoveryDepth). Replaced inline approximation with verbatim transpiler output. Removed stale NatSpec (no delegatecall), removed unused import. --- onchain/src/OptimizerV3.sol | 414 +++++++++++++++++++++++++----------- 1 file changed, 293 insertions(+), 121 deletions(-) diff --git a/onchain/src/OptimizerV3.sol b/onchain/src/OptimizerV3.sol index 35d22f1..68b2d24 100644 --- a/onchain/src/OptimizerV3.sol +++ b/onchain/src/OptimizerV3.sol @@ -2,56 +2,28 @@ 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. + * @notice UUPS-upgradeable Optimizer whose calculateParams is overridden by + * the Push3 transpiler output. The body below is a verbatim copy of + * OptimizerV3Push3.calculateParams — kept in sync by the deploy pipeline + * (transpile → overwrite this file → compile → upgrade). * - * @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) + * @dev No new storage slots. Only overrides the pure calculateParams function. + * Register-to-output mapping must match OptimizerV3Push3 exactly: + * r40 → ci, r39 → anchorShare, r38 → anchorWidth, r37 → discoveryDepth */ 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) + returns (uint256 ci, 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"); - } + // ── BEGIN TRANSPILER OUTPUT (optimizer_v3.push3) ── + // Do NOT edit by hand — regenerate via: npx tsx tools/push3-transpiler/transpile-cli.ts uint256 percentagestaked = uint256(uint256(inputs[0].mantissa)); uint256 taxrate = uint256(uint256(inputs[1].mantissa)); @@ -64,106 +36,306 @@ contract OptimizerV3 is Optimizer { if ((staked > 91)) { uint256 deltas = uint256((100 - staked)); - - // Tax rate index calculation (deep nested if-else chain) - uint256 r28; + uint256 r0; 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; + r0 = 0; } else { - r28 = 29; + uint256 r1; + if ((taxrate <= 412371134020618)) { + r1 = 1; + } else { + uint256 r2; + if ((taxrate <= 618556701030927)) { + r2 = 2; + } else { + uint256 r3; + if ((taxrate <= 1030927835051546)) { + r3 = 3; + } else { + uint256 r4; + if ((taxrate <= 1546391752577319)) { + r4 = 4; + } else { + uint256 r5; + if ((taxrate <= 2164948453608247)) { + r5 = 5; + } else { + uint256 r6; + if ((taxrate <= 2783505154639175)) { + r6 = 6; + } else { + uint256 r7; + if ((taxrate <= 3608247422680412)) { + r7 = 7; + } else { + uint256 r8; + if ((taxrate <= 4639175257731958)) { + r8 = 8; + } else { + uint256 r9; + if ((taxrate <= 5670103092783505)) { + r9 = 9; + } else { + uint256 r10; + if ((taxrate <= 7216494845360824)) { + r10 = 10; + } else { + uint256 r11; + if ((taxrate <= 9278350515463917)) { + r11 = 11; + } else { + uint256 r12; + if ((taxrate <= 11855670103092783)) { + r12 = 12; + } else { + uint256 r13; + if ((taxrate <= 15979381443298969)) { + r13 = 13; + } else { + uint256 r14; + if ((taxrate <= 22164948453608247)) { + r14 = 14; + } else { + uint256 r15; + if ((taxrate <= 29381443298969072)) { + r15 = 15; + } else { + uint256 r16; + if ((taxrate <= 38144329896907216)) { + r16 = 16; + } else { + uint256 r17; + if ((taxrate <= 49484536082474226)) { + r17 = 17; + } else { + uint256 r18; + if ((taxrate <= 63917525773195876)) + { + r18 = 18; + } else { + uint256 r19; + if ( + ( + taxrate + <= 83505154639175257 + ) + ) { + r19 = 19; + } else { + uint256 r20; + if ( + ( + taxrate + <= + 109278350515463917 + ) + ) { + r20 = 20; + } else { + uint256 r21; + if ( + ( + taxrate + <= + 144329896907216494 + ) + ) { + r21 = 21; + } else { + uint256 r22; + if ( + ( + taxrate + <= + 185567010309278350 + ) + ) { + r22 = 22; + } else { + uint256 r23; + if ( + ( + taxrate + <= + 237113402061855670 + ) + ) { + r23 = 23; + } else { + uint256 r24; + if ( + ( + taxrate + <= + 309278350515463917 + ) + ) { + r24 = 24; + } else { + uint256 + r25; + if ( + ( + taxrate + <= + 402061855670103092 + ) + ) { + r25 + = 25; + } else { + uint256 + r26; + if ( + ( + taxrate + <= + 520618556701030927 + ) + ) { + r26 + = + 26; + } + else + { + uint256 + r27; + if ( + ( + taxrate + <= + 680412371134020618 + ) + ) + { + r27 + = + 27; + } + else + { + uint256 + r28; + if ( + ( + taxrate + <= + 886597938144329896 + ) + ) + { + r28 + = + 28; + } + else + { + r28 + = + 29; + } + r27 + = + r28; + } + r26 + = + r27; + } + r25 + = + r26; + } + r24 = + r25; + } + r23 = r24; + } + r22 = r23; + } + r21 = r22; + } + r20 = r21; + } + r19 = r20; + } + r18 = r19; + } + r17 = r18; + } + r16 = r17; + } + r15 = r16; + } + r14 = r15; + } + r13 = r14; + } + r12 = r13; + } + r11 = r12; + } + r10 = r11; + } + r9 = r10; + } + r8 = r9; + } + r7 = r8; + } + r6 = r7; + } + r5 = r6; + } + r4 = r5; + } + r3 = r4; + } + r2 = r3; + } + r1 = r2; + } + r0 = r1; } - uint256 dup29 = r28; + uint256 dup29 = r0; uint256 r32; if ((dup29 >= 14)) { - uint256 dup30 = (dup29 + 1); - r32 = (dup30 > 29) ? 29 : dup30; + uint256 dup30 = uint256((dup29 + 1)); + if ((dup30 > 29)) { + r32 = 29; + } else { + r32 = 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 + r37 = uint256(1000000000000000000); + r38 = uint256(20); + r39 = uint256(1000000000000000000); + r40 = uint256(0); } else { - // Bear - r37 = 300000000000000000; // AS = 0.3e18 - r38 = 100; // AW = 100 - r39 = 300000000000000000; // DD = 0.3e18 - r40 = 0; // CI = 0 + r37 = uint256(300000000000000000); + r38 = uint256(100); + r39 = uint256(300000000000000000); + r40 = uint256(0); } } else { - // Bear (staked <= 91%) - r37 = 300000000000000000; - r38 = 100; - r39 = 300000000000000000; - r40 = 0; + r37 = uint256(300000000000000000); + r38 = uint256(100); + r39 = uint256(300000000000000000); + r40 = uint256(0); } - anchorShare = r37; + // Register-to-output mapping (matches OptimizerV3Push3 exactly) + ci = uint256(r40); + anchorShare = uint256(r39); anchorWidth = uint24(r38); - discoveryDepth = r39; - capitalInefficiency = r40; + discoveryDepth = uint256(r37); + // ── END TRANSPILER OUTPUT ── } }