{"item":"h4","experiment":"Offline aggregate-state H=4 Bellman fee table replacing G fee mapping; no next-mix","status":"completed","valid":true,"recommendation":"Reject this candidate and retain V2. The measured table loses edge. This does not establish a bound on other table policies or better offline state models.","code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {AMMStrategyBase} from \"./AMMStrategyBase.sol\";\nimport {TradeInfo} from \"./IAMMStrategy.sol\";\n\ncontract Strategy is AMMStrategyBase {\n    uint256 constant ELAPSED_CAP = 8;\n    uint256 constant SIGNAL_THRESHOLD = WAD / 650;\n    uint256 constant DIR_DECAY = 750000000000000000;\n    uint256 constant ACT_DECAY = 530000000000000000;\n    uint256 constant SIZE_DECAY = 530000000000000000;\n    uint256 constant TOX_DECAY = 910000000000000000;\n    uint256 constant SIGMA_DECAY = 690000000000000000;\n    uint256 constant LAMBDA_DECAY = 990000000000000000;\n    uint256 constant SIZE_BLEND_DECAY = 828000000000000000;\n    uint256 constant TOX_BLEND_DECAY = 51000000000000000;\n    uint256 constant ACT_BLEND_DECAY = 985000000000000000;\n    uint256 constant PHAT_ALPHA = 270000000000000000;\n    uint256 constant PHAT_ALPHA_RETAIL = 60000000000000000;\n    uint256 constant PHAT_ALPHA_SAME = 120000000000000000;\n    uint256 constant REVERT_U = 0;\n    uint256 constant DIR_IMPACT_MULT = 4;\n    uint256 constant GATE_SIGMA_MULT = 7200000000000000000;\n    uint256 constant MIN_GATE = 30000000000000000;\n    uint256 constant TRADE_TOX_BOOST = 3500 * BPS;\n    uint256 constant STALE_ATTRACT_FRAC = 1050000000000000000;\n    uint256 constant RET_CAP = WAD / 35;\n    uint256 constant TOX_CAP = WAD / 5;\n    uint256 constant TRADE_RATIO_CAP = WAD / 5;\n    uint256 constant LAMBDA_CAP = 1820000000000000000;\n    uint256 constant STEP_COUNT_CAP = 64;\n    uint256 constant BASE_FEE = 4 * BPS;\n    uint256 constant SIGMA_COEF = 200000000000000000;\n    uint256 constant LAMBDA_COEF = 12 * BPS;\n    uint256 constant FLOW_SIZE_COEF = 4842 * BPS;\n    uint256 constant TOX_COEF = 300 * BPS;\n    uint256 constant TOX_QUAD_COEF = 15000 * BPS;\n    uint256 constant ACT_COEF = 91843 * BPS;\n    uint256 constant DIR_COEF = 20 * BPS;\n    uint256 constant DIR_TOX_COEF = 100 * BPS;\n    uint256 constant STALE_DIR_COEF = 6850 * BPS;\n    uint256 constant SIGMA_TOX_COEF = 500 * BPS;\n    uint256 constant TAIL_KNEE = 600 * BPS;\n    uint256 constant TAIL_SLOPE_PROTECT = 930000000000000000;\n    uint256 constant TAIL_SLOPE_ATTRACT = 850000000000000000;\n\n    function afterInitialize(uint256 initialX, uint256 initialY) external override returns (uint256, uint256) {\n        slots[0] = BASE_FEE; slots[1] = BASE_FEE; slots[3] = WAD; \n        slots[5] = initialX > 0 ? wdiv(initialY, initialX) : 100 * WAD;\n        slots[6] = 950000000000000; slots[7] = 800000000000000000; slots[8] = 2000000000000000;\n        slots[13] = 902500000000; slots[14] = slots[5]; \n        return (BASE_FEE, BASE_FEE);\n    }\n\n    function afterSwap(TradeInfo calldata trade) external override returns (uint256, uint256) {\n        uint256 prevBidFee = slots[0]; uint256 prevAskFee = slots[1]; uint256 lastTs = uint64(slots[2]);\n        uint256 dirState = slots[3]; uint256 actEma = slots[4]; uint256 pHat = slots[5];\n        uint256 sigmaHat = slots[6]; uint256 lambdaHat = slots[7]; uint256 sizeHat = slots[8];\n        uint256 toxEma = slots[9]; uint256 stepTradeCount = slots[10];\n\n        uint256 sigmaForFast = sigmaHat;\n        uint256 fastHat = slots[14];\n        uint256 uncertainty = slots[13];\n        uint256 silent = trade.timestamp > lastTs ? trade.timestamp - lastTs : 0;\n        bool isNewStep = trade.timestamp > lastTs;\n        if (isNewStep) {\n            uint256 elapsedRaw = trade.timestamp - lastTs;\n            uint256 elapsed = elapsedRaw > ELAPSED_CAP ? ELAPSED_CAP : elapsedRaw;\n            dirState = _decayCentered(dirState, DIR_DECAY, elapsed);\n            actEma = wmul(actEma, _powWad(ACT_DECAY, elapsed));\n            sizeHat = wmul(sizeHat, _powWad(SIZE_DECAY, elapsed));\n            toxEma = wmul(toxEma, _powWad(TOX_DECAY, elapsed));\n            if (stepTradeCount > 0 && elapsedRaw > 0) {\n                uint256 lambdaInst = (stepTradeCount * WAD) / elapsedRaw;\n                if (lambdaInst > LAMBDA_CAP) lambdaInst = LAMBDA_CAP;\n                lambdaHat = wmul(lambdaHat, LAMBDA_DECAY) + wmul(lambdaInst, WAD - LAMBDA_DECAY);\n            }\n            uncertainty += wmul(sigmaForFast, sigmaForFast) * elapsedRaw;\n            if (uncertainty > 100000000000000) uncertainty = 100000000000000;\n            stepTradeCount = 0;\n        }\n\n        bool firstInStep = stepTradeCount == 0;\n        uint256 spot = trade.reserveX > 0 ? wdiv(trade.reserveY, trade.reserveX) : pHat;\n        if (pHat == 0) pHat = spot;\n\n        uint256 feeUsed = trade.isBuy ? prevBidFee : prevAskFee;\n        uint256 gamma = feeUsed < WAD ? WAD - feeUsed : 0;\n        uint256 pImplied;\n        if (gamma == 0) { pImplied = spot; }\n        else { pImplied = trade.isBuy ? wmul(spot, gamma) : wdiv(spot, gamma); }\n\n        // S: infer a no-trade interval center from the last post-trade spot.\n        uint256 silenceScale = WAD;\n        if (firstInStep && silent > 1) {\n            uint256 g = silent - 1;\n            if (g > 1) g = 1;\n            uint256 w = WAD - _powWad(800000000000000000, g);\n            uint256 s = slots[2] >> 64;\n            if (s == 0) s = pHat;\n            uint256 c = (wmul(s, WAD - prevBidFee) + wdiv(s, WAD - prevAskFee)) / 2;\n            if (c >= pHat) pHat += wmul(w, c - pHat);\n            else pHat -= wmul(w, pHat - c);\n            silenceScale = WAD - wmul(300000000000000000, w);\n        }\n\n        {\n            uint256 ret = pHat > 0 ? wdiv(absDiff(pImplied, pHat), pHat) : 0;\n            uint256 alpha = firstInStep ? PHAT_ALPHA : PHAT_ALPHA_RETAIL;\n            uint256 prePhat = pHat;\n            bool secondPrint = !firstInStep && stepTradeCount == 1;\n            bool sameDir = false; bool oppDir = false;\n            if (secondPrint) {\n                bool up2 = pImplied >= pHat;\n                uint256 d1 = slots[12];\n                if (d1 != 0) { sameDir = (d1 == 1) == up2; oppDir = !sameDir; }\n                if (sameDir) alpha = PHAT_ALPHA_SAME;\n            }\n            if (firstInStep) { slots[12] = pImplied >= pHat ? 1 : 2; }\n            uint256 adaptiveGate = wmul(sigmaHat, GATE_SIGMA_MULT);\n            if (adaptiveGate < MIN_GATE) adaptiveGate = MIN_GATE;\n            alpha = wmul(alpha, silenceScale);\n            adaptiveGate = wmul(adaptiveGate, silenceScale);\n            if (ret <= adaptiveGate) { pHat = wmul(pHat, WAD - alpha) + wmul(pImplied, alpha); }\n            if (oppDir && REVERT_U > 0) {\n                uint256 pre = slots[11];\n                if (pre > pHat) pHat = pHat + wmul(pre - pHat, REVERT_U);\n                else pHat = pHat - wmul(pHat - pre, REVERT_U);\n            }\n            if (firstInStep) {\n                if (ret > RET_CAP) ret = RET_CAP;\n                sigmaHat = wmul(sigmaHat, SIGMA_DECAY) + wmul(ret, WAD - SIGMA_DECAY);\n            }\n        }\n\n        // Interior retail routing equalizes fee-adjusted marginal prices.\n        // Subsequent trades in a step cannot be the initial arbitrage trade.\n        if (!firstInStep && feeUsed > 30 * BPS && gamma > 0) {\n            uint256 normalSpot = trade.isBuy\n                ? wdiv(wmul(spot, gamma), WAD - 30 * BPS)\n                : wdiv(wmul(spot, WAD - 30 * BPS), gamma);\n            pHat = wmul(pHat, 90 * WAD / 100) + wmul(normalSpot, 10 * WAD / 100);\n        }\n\n        {\n            uint256 ret = fastHat > 0 ? wdiv(absDiff(pImplied, fastHat), fastHat) : 0;\n            uint256 alpha;\n            if (firstInStep) {\n                uint256 processSigma = sigmaForFast;\n                uint256 obsVar = uncertainty + wmul(processSigma, processSigma);\n                uint256 probArb;\n                uint256 z2 = wdiv(wmul(ret, ret), obsVar);\n                uint256 density = _powWad(wdiv(WAD, WAD + z2 / 16), 8);\n                uint256 sigmaObs = _isqrt(obsVar * WAD);\n                uint256 odds = wmul(density, wdiv(6700000000000000, sigmaObs));\n                bool arbFlag = ret <= wmul(sigmaForFast, 1220000000000000000);\n                uint256 prior = arbFlag ? 650000000000000000 : 400000000000000000;\n                uint256 tr = trade.reserveY > 0 ? wdiv(trade.amountY, trade.reserveY) : 0;\n                if (tr > 3000000000000000) prior = wmul(prior, 6 * WAD / 10);\n                if (silent > 1) prior = wmul(prior, 8 * WAD / 10);\n                odds = wmul(odds, wdiv(prior, WAD - prior));\n                probArb = wdiv(odds, WAD + odds);\n                alpha = wmul(probArb, 600000000000000000) + wmul(WAD - probArb, 80000000000000000);\n                slots[15] = pImplied >= fastHat ? 1 : 2;\n                uncertainty = wmul(uncertainty, WAD - alpha);\n            } else {\n                if ((slots[15] == 1) == (pImplied >= fastHat)) alpha = PHAT_ALPHA_RETAIL;\n            }\n            uint256 gate = wmul(sigmaHat, GATE_SIGMA_MULT);\n            if (gate < MIN_GATE) gate = MIN_GATE;\n            if (ret <= gate) fastHat = wmul(fastHat, WAD - alpha) + wmul(pImplied, alpha);\n            slots[13] = uncertainty;\n        }\n\n        if (!firstInStep && feeUsed > 30 * BPS && gamma > 0) {\n            uint256 normalObs = trade.isBuy\n                ? wdiv(wmul(spot, gamma), WAD - 30 * BPS)\n                : wdiv(wmul(spot, WAD - 30 * BPS), gamma);\n            if ((slots[15] == 1) == (normalObs >= fastHat)) {\n                fastHat = wmul(fastHat, 9 * WAD / 10) + wmul(normalObs, WAD / 10);\n            }\n        }\n        slots[14] = fastHat;\n        uint256 tradeRatio = trade.reserveY > 0 ? wdiv(trade.amountY, trade.reserveY) : 0;\n        if (tradeRatio > TRADE_RATIO_CAP) tradeRatio = TRADE_RATIO_CAP;\n\n        if (tradeRatio > SIGNAL_THRESHOLD) {\n            uint256 push = tradeRatio * DIR_IMPACT_MULT;\n            if (push > WAD / 4) push = WAD / 4;\n            if (trade.isBuy) {\n                dirState = dirState + push;\n                if (dirState > 2 * WAD) dirState = 2 * WAD;\n            } else {\n                dirState = dirState > push ? dirState - push : 0;\n            }\n            actEma = wmul(actEma, ACT_BLEND_DECAY) + wmul(tradeRatio, WAD - ACT_BLEND_DECAY);\n            sizeHat = wmul(sizeHat, SIZE_BLEND_DECAY) + wmul(tradeRatio, WAD - SIZE_BLEND_DECAY);\n            if (sizeHat > WAD) sizeHat = WAD;\n        }\n\n        uint256 tox = pHat > 0 ? wdiv(absDiff(spot, pHat), pHat) : 0;\n        if (tox > TOX_CAP) tox = TOX_CAP;\n        toxEma = wmul(toxEma, TOX_BLEND_DECAY) + wmul(tox, WAD - TOX_BLEND_DECAY);\n        uint256 toxSignal = toxEma;\n\n        stepTradeCount = stepTradeCount + 1;\n        if (stepTradeCount > STEP_COUNT_CAP) stepTradeCount = STEP_COUNT_CAP;\n\n        uint256 staleHat = wmul(pHat, 700000000000000000) + wmul(fastHat, 300000000000000000);\n        uint256 gap = wdiv(absDiff(spot, staleHat), staleHat);\n        bool above = spot >= staleHat;\n        uint256 gi;\n        if (above) { gi = gap < 1000000000000000 ? 3 : gap < 4000000000000000 ? 4 : gap < 9000000000000000 ? 5 : 6; }\n        else { gi = gap <= 1000000000000000 ? 3 : gap <= 4000000000000000 ? 2 : gap <= 9000000000000000 ? 1 : 0; }\n        uint256 flow = wmul(lambdaHat, sizeHat);\n        uint256 fi = flow < 600000000000000 ? 0 : flow < 1400000000000000 ? 1 : 2;\n        bytes memory table = hex\"010101010101010101010101040404040404040404040404040404040404030303030303030303030303\";\n        uint256 action = uint8(table[(gi * 3 + fi) * 2 + (stepTradeCount > 1 ? 1 : 0)]);\n        uint256 bidFee = _level(action / 3);\n        uint256 askFee = _level(action % 3);\n        uint256 recenter = wmul(gap, 850000000000000000);\n        if (above) { bidFee += recenter; askFee = askFee > recenter ? askFee - recenter : 0; }\n        else { askFee += recenter; bidFee = bidFee > recenter ? bidFee - recenter : 0; }\n        uint256 dirDev = dirState >= WAD ? dirState - WAD : WAD - dirState;\n        uint256 skew = wmul(DIR_COEF, dirDev) + wmul(DIR_TOX_COEF, wmul(dirDev, toxSignal));\n        if (dirState >= WAD) { bidFee += skew; askFee = askFee > skew ? askFee - skew : 0; }\n        else { askFee += skew; bidFee = bidFee > skew ? bidFee - skew : 0; }\n        bidFee = clampFee(bidFee); askFee = clampFee(askFee);\n\n        slots[0] = bidFee; slots[1] = askFee; slots[2] = (spot << 64) | trade.timestamp;\n        slots[3] = dirState; slots[4] = actEma; slots[5] = pHat;\n        slots[6] = sigmaHat; slots[7] = lambdaHat; slots[8] = sizeHat;\n        slots[9] = toxEma; slots[10] = stepTradeCount;\n\n        return (bidFee, askFee);\n    }\n\n    function _level(uint256 a) internal pure returns (uint256) { return a == 0 ? 20 * BPS : a == 1 ? 45 * BPS : 80 * BPS; }\n\n    function _compressTailWithSlope(uint256 fee, uint256 slope) internal pure returns (uint256) {\n        if (fee <= TAIL_KNEE) return fee;\n        return TAIL_KNEE + wmul(fee - TAIL_KNEE, slope);\n    }\n\n    function _powWad(uint256 factor, uint256 exp) internal pure returns (uint256 result) {\n        result = WAD;\n        while (exp > 0) {\n            if (exp & 1 == 1) result = wmul(result, factor);\n            factor = wmul(factor, factor);\n            exp >>= 1;\n        }\n    }\n\n    function _decayCentered(uint256 centered, uint256 decayFactor, uint256 elapsed) internal pure returns (uint256) {\n        uint256 mul = _powWad(decayFactor, elapsed);\n        if (centered >= WAD) { return WAD + wmul(centered - WAD, mul); }\n        uint256 below = wmul(WAD - centered, mul);\n        return below < WAD ? WAD - below : 0;\n    }\n\n    // Floor square root: bit-length seed and seven Newton steps (all uint256).\n    function _isqrt(uint256 x) internal pure returns (uint256 r) {\n        if (x == 0) return 0;\n        unchecked {\n            uint256 y = x;\n            r = 1;\n            if (y >> 128 != 0) { y >>= 128; r <<= 64; }\n            if (y >> 64 != 0) { y >>= 64; r <<= 32; }\n            if (y >> 32 != 0) { y >>= 32; r <<= 16; }\n            if (y >> 16 != 0) { y >>= 16; r <<= 8; }\n            if (y >> 8 != 0) { y >>= 8; r <<= 4; }\n            if (y >> 4 != 0) { y >>= 4; r <<= 2; }\n            if (y >> 2 != 0) { r <<= 1; }\n            r = (r + x / r) >> 1;\n            r = (r + x / r) >> 1;\n            r = (r + x / r) >> 1;\n            r = (r + x / r) >> 1;\n            r = (r + x / r) >> 1;\n            r = (r + x / r) >> 1;\n            r = (r + x / r) >> 1;\n            uint256 t = x / r;\n            return r < t ? r : t;\n        }\n    }\n\n    function getName() external pure override returns (string memory) { return \"h4a\"; }\n}\n","sha256":"2e0d6b44b102b1ceacc689aec0c712b9558718bdde0b4b365f4bf39275609978","support_sources":{"AMMStrategyBase.sol":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {IAMMStrategy, TradeInfo} from \"./IAMMStrategy.sol\";\n\n/// @title AMM Strategy Base Contract\n/// @notice Base contract that all user strategies must inherit from\n/// @dev Provides fixed storage slots, helper functions, and fee clamping\nabstract contract AMMStrategyBase is IAMMStrategy {\n    /*//////////////////////////////////////////////////////////////\n                               CONSTANTS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice 1e18 - represents 100% in WAD precision\n    uint256 public constant WAD = 1e18;\n\n    /// @notice Maximum allowed fee: 10% (1e17)\n    uint256 public constant MAX_FEE = WAD / 10;\n\n    /// @notice Minimum allowed fee: 0\n    uint256 public constant MIN_FEE = 0;\n\n    /// @notice 1 basis point in WAD (0.01% = 0.0001 = 1e14)\n    uint256 public constant BPS = 1e14;\n\n    /*//////////////////////////////////////////////////////////////\n                            STORAGE SLOTS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Fixed storage array - strategies can only use these 32 slots\n    /// @dev This provides 1KB of persistent storage per strategy\n    /// @dev Slot access is validated at the EVM level (array bounds)\n    uint256[32] public slots;\n\n    /*//////////////////////////////////////////////////////////////\n                            HELPER FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Multiply two WAD values\n    /// @param x First value (WAD)\n    /// @param y Second value (WAD)\n    /// @return Result in WAD precision\n    function wmul(uint256 x, uint256 y) internal pure returns (uint256) {\n        return (x * y) / WAD;\n    }\n\n    /// @notice Divide two WAD values\n    /// @param x Numerator (WAD)\n    /// @param y Denominator (WAD)\n    /// @return Result in WAD precision\n    function wdiv(uint256 x, uint256 y) internal pure returns (uint256) {\n        return (x * WAD) / y;\n    }\n\n    /// @notice Clamp a value between min and max\n    /// @param value Value to clamp\n    /// @param minVal Minimum value\n    /// @param maxVal Maximum value\n    /// @return Clamped value\n    function clamp(uint256 value, uint256 minVal, uint256 maxVal) internal pure returns (uint256) {\n        if (value < minVal) return minVal;\n        if (value > maxVal) return maxVal;\n        return value;\n    }\n\n    /// @notice Convert basis points to WAD\n    /// @param bps Basis points (1 bps = 0.01%)\n    /// @return WAD value\n    function bpsToWad(uint256 bps) internal pure returns (uint256) {\n        return bps * BPS;\n    }\n\n    /// @notice Convert WAD to basis points\n    /// @param wadValue WAD value\n    /// @return Basis points\n    function wadToBps(uint256 wadValue) internal pure returns (uint256) {\n        return wadValue / BPS;\n    }\n\n    /// @notice Clamp fee to valid range [0, MAX_FEE]\n    /// @param fee Fee value to clamp\n    /// @return Clamped fee value\n    function clampFee(uint256 fee) internal pure returns (uint256) {\n        return clamp(fee, MIN_FEE, MAX_FEE);\n    }\n\n    /// @notice Calculate absolute difference between two values\n    /// @param a First value\n    /// @param b Second value\n    /// @return Absolute difference\n    function absDiff(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a - b : b - a;\n    }\n\n    /// @notice Simple integer square root (Babylonian method)\n    /// @param x Value to take sqrt of\n    /// @return y Square root\n    function sqrt(uint256 x) internal pure returns (uint256 y) {\n        if (x == 0) return 0;\n        uint256 z = (x + 1) / 2;\n        y = x;\n        while (z < y) {\n            y = z;\n            z = (x / z + z) / 2;\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                          SLOT HELPERS\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Read a slot value\n    /// @param index Slot index (0-31)\n    /// @return Value stored in the slot\n    function readSlot(uint256 index) internal view returns (uint256) {\n        require(index < 32, \"Slot index out of bounds\");\n        return slots[index];\n    }\n\n    /// @notice Write a value to a slot\n    /// @param index Slot index (0-31)\n    /// @param value Value to store\n    function writeSlot(uint256 index, uint256 value) internal {\n        require(index < 32, \"Slot index out of bounds\");\n        slots[index] = value;\n    }\n}\n","IAMMStrategy.sol":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\n/// @title Trade information passed to AMM strategies\n/// @notice Contains all data about an executed trade that strategies can use to adjust fees\nstruct TradeInfo {\n    bool isBuy;          // true if AMM bought X (trader sold X)\n    uint256 amountX;     // Amount of X traded (WAD precision, 1e18)\n    uint256 amountY;     // Amount of Y traded (WAD precision, 1e18)\n    uint256 timestamp;   // Simulation step number\n    uint256 reserveX;    // Post-trade X reserves (WAD precision)\n    uint256 reserveY;    // Post-trade Y reserves (WAD precision)\n}\n\n/// @title AMM Strategy Interface\n/// @notice Interface that all AMM fee strategies must implement\n/// @dev Fees are returned as WAD values (1e18 = 100%, 1e15 = 0.1% = 10bps)\ninterface IAMMStrategy {\n    /// @notice Initialize the strategy with starting reserves\n    /// @param initialX Starting X reserve amount (WAD precision)\n    /// @param initialY Starting Y reserve amount (WAD precision)\n    /// @return bidFee Fee when AMM buys X (WAD precision, e.g., 30e14 = 30bps)\n    /// @return askFee Fee when AMM sells X (WAD precision, e.g., 30e14 = 30bps)\n    function afterInitialize(uint256 initialX, uint256 initialY) external returns (uint256 bidFee, uint256 askFee);\n\n    /// @notice Called after each trade to update fees\n    /// @param trade Information about the just-executed trade\n    /// @return bidFee Updated fee when AMM buys X (WAD precision)\n    /// @return askFee Updated fee when AMM sells X (WAD precision)\n    function afterSwap(TradeInfo calldata trade) external returns (uint256 bidFee, uint256 askFee);\n\n    /// @notice Get the strategy name for display\n    /// @return Strategy name string\n    function getName() external view returns (string memory);\n}\n"},"reference":{"v2_sha256":"28417e116f57f1029fdd1803832e852574902c1ae7253c05657f317db76da4ab","g_sha256":"610c1905e7dd5559b84e40a3b2d6f8e0b53a7b0ac7574ae33b6c1770a28367cb","g_recovery":"Removed MIX_ constants, next-retail-mix block and Poisson helper block as specified by Gsrc.notes.G_recovery; both reference hashes verified before experimentation.","artifact_H":"https://api.imd.fun/artifacts/db62deadd0a3ec885ad69bd3917fee793a924ead522776d73cc09110923e1e86","artifact_G":"https://api.imd.fun/artifacts/f09f39f5092e5b1e56f156df10f397e5df0e194afa630ab24fc699adfd980d31","rules":"https://api.imd.fun/artifacts/ddbbaac58282566e0505d895c83daf348487cc322e8c482e61d4d87e6e4628de"},"method":{"repository":"https://github.com/benedictbrady/amm-challenge","commit":"6b6921f8d463314aa7c96234e1be25a25245f704","setup":"Prescribed H setup run once with requested cargo fallback replacement; starter validation passed; supplied instrumentation.patch applied and maturin release rebuild passed.","batch_call":"amm_sim_rs.run_batch(X, VanillaStrategy, configs, 8), each X in a separate market; chunks of 8 seeds","configs":"H harness config_for_seed: numpy.default_rng(seed), draw size uniform(19,21), rate uniform(0.6,1.0), sigma uniform(0.000882,0.001008), in that order; price seed=seed, retail seed+1.","fixed_config":{"n_steps":10000,"initial_price":100,"initial_x":100,"initial_y":10000,"gbm_mu":0,"gbm_dt":1,"retail_buy_prob":0.5,"retail_size_sigma":1.2,"normalizer_fee_bps":30,"afterSwap_gas_cap":250000},"compile":{"solc":"0.8.24","optimizer_runs":200,"viaIR":true,"evmVersion":"paris","amm_match_validate":"passed"},"statistics":"Per-seed candidate edge minus V2 edge on identical configs; mean arithmetic; se=sample SD/sqrt(n); worst=min paired difference. Edge and its retail/arb components are Y units per 10000-step simulation, not terminal PnL.","gas":"max_ok is maximum successful afterSwap gas. max_ok_all_callbacks and callback counters also included. Other errors=sum revert, tx_error, other_halt, bad_return. Valid iff candidate OOG<=V2 OOG, other errors zero, no Vanilla failures, per-seed/global counters equal, and abs(retail+arb-total)<1e-8.","terciles":"Sort the 2000 V2 submission retail_volume_y observations ascending (seed breaks ties); low 667, middle 667, high 666. All terciles use the same frozen candidate and reference seeds. Deltas are actual engine retail_edges and arb_edges, never inferred from fees or total.","no_board_claim":"Local simulator measurements only; no challenge submission or leaderboard measurement performed."},"table":{"selected":"h4a","horizon_steps":4,"shape":[7,3,2],"index":"(gap_bin*3+flow_bin)*2+count_bin; count_bin=stepTradeCount>1 after including triggering trade.","gap":"spot/(0.7*pHat+0.3*fastHat)-1; signed, using G/V2 observable estimators only.","gap_centers":[-0.012,-0.006,-0.002,0,0.002,0.006,0.012],"gap_cuts":[-0.009,-0.004,-0.001,0.001,0.004,0.009],"flow":"lambdaHat*sizeHat in WAD arithmetic","flow_centers":[0.00035,0.001,0.0022],"flow_cuts":[0.0006,0.0014],"joint_actions_bps":[[20,20],[20,45],[20,80],[45,20],[45,45],[45,80],[80,20],[80,45],[80,80]],"policy":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3],"hex":"010101010101010101010101040404040404040404040404040404040404030303030303030303030303","mapping":"Select joint base bid/ask fees, add 0.85*signed_gap to bid and subtract it from ask with floor zero, then apply the unchanged V2 DIR_COEF/DIR_TOX_COEF direction skew and clamp to MAX_FEE. G fBase/fMid, stale fee shifts, trade boost and tail compression are replaced. No next-mix.","runtime_inputs":"TradeInfo and retained G/V2 observable estimators, gap, flow, own executed trade count, direction state. No latent fair price, opponent reserves, seed, future, or final-print flag.","generator":"\"\"\"Offline aggregate-state Bellman experiment. A transition comprises current\nremaining Poisson retail prints then one next-step arb attempt per pool. Exact\nCFMM and router equations; approximate observable-estimator transitions and\nconditional latent distribution, explicitly not the exact V2 posterior.\nEach h uses h-1 callback policy and continuation values. No final-print feature.\n\"\"\"\nimport json,hashlib,itertools\nfrom pathlib import Path\nimport numpy as np\nGAP=np.array([-.012,-.006,-.002,0,.002,.006,.012]);CUT=np.array([-.009,-.004,-.001,.001,.004,.009])\nFLOW=np.array([.00035,.001,.0022]);FCUT=np.array([.0006,.0014])\nACTIONS=np.array(list(itertools.product([.002,.0045,.008],repeat=2)))\nSTATES=list(itertools.product(range(7),range(3),range(2)));N=4096\n\ndef index(spot,hat,flow,count):\n return (np.searchsorted(CUT,spot/hat-1)*3+np.searchsorted(FCUT,flow))*2+(count>1)\ndef fees(a,spot,hat,shift):\n d=shift*(spot/hat-1)\n return np.clip(ACTIONS[a,0]+d,0,.1),np.clip(ACTIONS[a,1]-d,0,.1)\ndef observe(hat,spot,fee,isbuy,count):\n implied=np.where(isbuy,spot*(1-fee),spot/(1-fee));alpha=np.where(count==1,.32,.065)\n return np.where(abs(implied/hat-1)<.03,hat*(1-alpha)+implied*alpha,hat)\ndef arb(x,y,p,bid,ask):\n k=x*y;buy=y/x<p;ga=1-ask;gb=1-bid\n qb=np.minimum(np.maximum(x-np.sqrt(k/(ga*p)),0),.99*x);yi=(k/(x-qb)-y)/ga\n qs=np.maximum((np.sqrt(k*gb/p)-x)/gb,0);yo=y-k/(x+gb*qs)\n execute=np.where(buy,p*qb-yi>0,yo-p*qs>0)\n edge=np.where(execute,np.where(buy,yi-p*qb,p*qs-yo),0)\n xn=np.where(buy,x-qb,x+gb*qs);yn=k/xn\n return np.where(execute,xn,x),np.where(execute,yn,y),edge,execute,~buy\n\ndef transition(gi,fi,ci,action,policy,value,shift,u):\n rng=np.random.default_rng(91731+gi*6+fi*2+ci)\n hat=np.full(N,100.);spot=np.full(N,100*(1+GAP[gi]));x=np.sqrt(1e6/spot);y=1e6/x\n p=100*np.exp(rng.normal(-.5*u*u,u,N))\n os=p*np.exp(rng.uniform(np.log(.997),-np.log(.997),N));ox=np.sqrt(1e6/os);oy=1e6/ox\n flow=np.full(N,FLOW[fi]);count=np.full(N,ci+1);bid,ask=fees(np.full(N,action),spot,hat,shift)\n remaining=rng.poisson(.8,N);score=np.zeros(N);mean=FLOW[fi]*10000/.8\n for j in range(int(remaining.max())):\n  live=remaining>j;buy=rng.random(N)<.5\n  size=np.exp(np.log(mean)-.5*1.2**2+rng.normal(0,1.2,N));total=np.where(buy,size,size/p)\n  fee=np.where(buy,ask,bid);gamma=1-fee;r=np.sqrt(x*y*gamma/(ox*oy*.997))\n  a=np.where(buy,y,x);b=np.where(buy,oy,ox)\n  ours=np.clip((r*(b+.997*total)-a)/(gamma+r*.997),0,total);theirs=total-ours\n  own=live&(ours>.0001);other=live&(theirs>.0001);k=x*y;ok=ox*oy\n  out=np.where(buy,x-k/(y+gamma*ours),y-k/(x+gamma*ours))\n  score+=np.where(own,np.where(buy,ours-p*out,p*ours-out),0)\n  nx=np.where(buy,k/(y+gamma*ours),x+gamma*ours);x=np.where(own,nx,x);y=k/x\n  nox=np.where(buy,ok/(oy+.997*theirs),ox+.997*theirs);ox=np.where(other,nox,ox);oy=ok/ox\n  count+=own;hat=np.where(own,observe(hat,y/x,fee,~buy,count),hat)\n  a=policy[index(y/x,hat,flow,count)];nb,na=fees(a,y/x,hat,shift)\n  bid=np.where(own,nb,bid);ask=np.where(own,na,ask)\n sigma=.000945;p*=np.exp(-.5*sigma*sigma+rng.normal(0,sigma,N))\n x,y,e,executed,isbuy=arb(x,y,p,bid,ask)\n ox,oy,_,_,_=arb(ox,oy,p,np.full(N,.003),np.full(N,.003));score+=e\n hat=np.where(executed,observe(hat,y/x,np.where(isbuy,bid,ask),isbuy,np.ones(N,dtype=int)),hat)\n # Empty-callback boundaries project to count=1; flow is held over the 4 steps.\n nxt=index(y/x,hat,flow,np.ones(N,dtype=int))\n return float(np.mean(score+value[nxt]))\ndef solve(horizon,shift,u):\n v=np.zeros(42);policy=np.full(42,4,dtype=int);history=[]\n for h in range(1,horizon+1):\n  q=np.array([[transition(*s,a,policy,v,shift,u) for a in range(9)] for s in STATES])\n  policy=np.argmax(q,axis=1);v=q[np.arange(42),policy]\n  history.append({'h':h,'policy':policy.tolist(),'value':v.tolist()})\n return history\n\nif __name__ == '__main__':\n specs=[('h4a',.85,.0018,4,[20,45,80]),('h4b',1.05,.0018,4,[20,45,80]),('h4c',.85,.003,4,[20,45,80]),('h1',.85,.0018,1,[20,45,80]),('h4d',.60,.0018,4,[20,45,80]),('h4e',.60,.0012,4,[10,30,60])]\n out=[]\n for name,shift,u,h,levels in specs:\n  ACTIONS=np.array(list(itertools.product([a/10000 for a in levels],repeat=2)))\n  hist=solve(h,shift,u)\n  out.append(dict(name=name,history=hist))\n print(json.dumps(out))\n","generator_dependency":"numpy from the prescribed simulator setup; Solidity runtime has no new dependency.","offline_integrated_model":"4096 Monte Carlo samples per aggregate state and action; common private synthetic RNG seeds 91731+6*gap_bin+2*flow_bin+count_bin, independent of competition seed ranges. True fair price lognormal around hat with sigma=0.0018, mean 100. Opponent spot log-uniform across its 30bps band around true fair, invariant k=1e6. Mean size=flow*10000/0.8 and lognormal sigma=1.2. Remaining current prints Poisson(0.8), side Bernoulli(0.5). Exact two-pool router splits, dust threshold, input fees in separate buckets, CFMM reserves, gross-flow trade edge, and next-step arb equations/cap. Next price lognormal sigma=0.000945. Each transition ends after one next-step arb attempt per pool, then adds previous-horizon aggregate-state value; later retail callbacks use previous-horizon policy. H=4 backward induction values later reserve recentering.","limitations":["Synthetic latent prior and opponent-reserve prior are assumptions, not fitted posteriors from training.","Offline observation transition is a proxy: implied execution price updates hat with alpha .32 for count=1, .065 later, gated at 3%; runtime retains actual G/V2 estimators.","Flow is held fixed across the four offline steps. Empty-callback boundaries are projected to count=1. Direction skew is retained at runtime but integrated as zero in the offline planner.","Aggregate-state projection and finite Monte Carlo integration make this an approximate finite-horizon policy, not an exact optimal policy for the simulator."],"selected_horizon_policies":[{"h":1,"policy":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3]},{"h":2,"policy":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3]},{"h":3,"policy":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3]},{"h":4,"policy":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3]}],"variants":[{"name":"h4a","horizon":4,"shift":0.85,"latent_log_sigma":0.0018,"table":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3],"sha256":"2e0d6b44b102b1ceacc689aec0c712b9558718bdde0b4b365f4bf39275609978","action_levels_bps":[20,45,80]},{"name":"h4b","horizon":4,"shift":1.05,"latent_log_sigma":0.0018,"table":[0,0,0,0,1,1,1,1,0,0,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,3,3,0,0,0,0,0,0],"sha256":"1635cad316eabea39d2e741aa9fe920aa21074f718d860ea2fb6c7b113d6e8cb","action_levels_bps":[20,45,80]},{"name":"h4c","horizon":4,"shift":0.85,"latent_log_sigma":0.003,"table":[2,2,2,2,2,2,2,2,1,1,1,1,4,4,4,4,8,8,4,4,4,4,4,5,4,4,4,4,4,4,6,3,3,3,6,6,6,6,6,6,6,6],"sha256":"03e88e09d20a3720bbba2eb01ed343267ecc99fa36436cd691e406b0cfe58c25","action_levels_bps":[20,45,80]},{"name":"h1","horizon":1,"shift":0.85,"latent_log_sigma":0.0018,"table":[1,1,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3],"sha256":"105379694783ea9426712d0b2d9da88438e753d9e54bb8cb1c781ea2645f2108","action_levels_bps":[20,45,80]},{"name":"h4d","horizon":4,"shift":0.6,"latent_log_sigma":0.0018,"action_levels_bps":[20,45,80],"table":[2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,3,3,4,3,4,4,3,3,3,3,7,6,6,6,6,6,6,6],"sha256":"4a6de25d1c91dfcfc19df9825e33f1cc51f340318c951a7424a6ba03fb3a58ac"},{"name":"h4e","horizon":4,"shift":0.6,"latent_log_sigma":0.0012,"action_levels_bps":[10,30,60],"table":[2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,8,8,4,4,4,4,5,5,4,4,4,4,7,7,6,6,6,6,6,6,6,6,6,6,6,6],"sha256":"d6be0deeb3b45d2c9899f609cd16529424c1223d2a57e2a871ae4ca3e3f0de05"}]},"seed_ranges":{"smoke":[20000,20007],"training":[20000,20063],"top2":[22000,22255],"confirmation":[4270000,4271999],"endpoints":"inclusive","confirmation_runs_per_strategy":1,"variants_total_including_h1":6,"selection":"Best valid H=4 training means select top2, best valid top2 mean selects frozen h4a. H1 is ablation only."},"smoke":{"candidate":{"n":8,"seconds":1.0543594360351562,"gas":{"max_ok":181881,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"checks":{"n":8,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.934897101018578e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"v2":{"n":8,"seconds":1.8118176460266113,"gas":{"max_ok":215713,"max_ok_all_callbacks":236377,"oog":0,"other_errors":0},"checks":{"n":8,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":4.149569576838985e-12,"normalizer_oog":0,"normalizer_other_errors":0}}},"training":[{"name":"h4a","sha256":"2e0d6b44b102b1ceacc689aec0c712b9558718bdde0b4b365f4bf39275609978","seed_range_inclusive":[20000,20063],"valid":true,"paired":{"n":64,"mean_diff":-23.57027653292986,"se":0.5452365958989239,"worst":-35.476593184804756,"worst_seed":20048},"checks":{"candidate":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.934897101018578e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.792788553866558e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":7.918865442276001,"v2":13.467012643814087},"gas":{"max_ok":208137,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":241967,"max_ok_all_callbacks":241967,"oog":0,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":64,"candidate":{"total":485.16682467691885,"retail":500.01210560362625,"arb":-14.84528092670746},"v2":{"total":508.73710120984873,"retail":534.8510488788927,"arb":-26.11394766904394},"delta":{"total":{"n":64,"mean":-23.57027653292986,"se":0.5452365958989239},"retail":{"n":64,"mean":-34.838943275266416,"se":0.5275565700162362},"arb":{"n":64,"mean":11.268666742336483,"se":0.25081404842339483}},"v2_retail_volume_y_range":[58425.88710375651,93934.40079231845]}}},{"name":"h4b","sha256":"1635cad316eabea39d2e741aa9fe920aa21074f718d860ea2fb6c7b113d6e8cb","seed_range_inclusive":[20000,20063],"valid":true,"paired":{"n":64,"mean_diff":-43.04806439703095,"se":1.686969137808068,"worst":-105.09263745737064,"worst_seed":20000},"checks":{"candidate":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":1.1766587704187259e-11,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.792788553866558e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":7.424489736557007,"v2":13.467012643814087},"gas":{"max_ok":208137,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":241967,"max_ok_all_callbacks":241967,"oog":0,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":64,"candidate":{"total":465.6890368128178,"retail":476.73202630843485,"arb":-11.042989495617055},"v2":{"total":508.73710120984873,"retail":534.8510488788927,"arb":-26.11394766904394},"delta":{"total":{"n":64,"mean":-43.04806439703095,"se":1.686969137808068},"retail":{"n":64,"mean":-58.119022570457815,"se":1.8068789079446284},"arb":{"n":64,"mean":15.070958173426886,"se":0.3245576591567941}},"v2_retail_volume_y_range":[58425.88710375651,93934.40079231845]}}},{"name":"h4c","sha256":"03e88e09d20a3720bbba2eb01ed343267ecc99fa36436cd691e406b0cfe58c25","seed_range_inclusive":[20000,20063],"valid":true,"paired":{"n":64,"mean_diff":-64.09074177259053,"se":1.094925872981095,"worst":-85.2820337033603,"worst_seed":20048},"checks":{"candidate":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":8.185452315956354e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.792788553866558e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":6.607989072799683,"v2":13.467012643814087},"gas":{"max_ok":208137,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":241967,"max_ok_all_callbacks":241967,"oog":0,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":64,"candidate":{"total":444.6463594372582,"retail":453.49475012820665,"arb":-8.848390690948456},"v2":{"total":508.73710120984873,"retail":534.8510488788927,"arb":-26.11394766904394},"delta":{"total":{"n":64,"mean":-64.09074177259053,"se":1.094925872981095},"retail":{"n":64,"mean":-81.35629875068604,"se":1.1746793617118139},"arb":{"n":64,"mean":17.265556978095486,"se":0.23486994398580466}},"v2_retail_volume_y_range":[58425.88710375651,93934.40079231845]}}},{"name":"h1","sha256":"105379694783ea9426712d0b2d9da88438e753d9e54bb8cb1c781ea2645f2108","seed_range_inclusive":[20000,20063],"valid":true,"paired":{"n":64,"mean_diff":-23.57027653292986,"se":0.5452365958989239,"worst":-35.476593184804756,"worst_seed":20048},"checks":{"candidate":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.934897101018578e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.792788553866558e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":8.922613143920898,"v2":13.467012643814087},"gas":{"max_ok":208137,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":241967,"max_ok_all_callbacks":241967,"oog":0,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":64,"candidate":{"total":485.16682467691885,"retail":500.01210560362625,"arb":-14.84528092670746},"v2":{"total":508.73710120984873,"retail":534.8510488788927,"arb":-26.11394766904394},"delta":{"total":{"n":64,"mean":-23.57027653292986,"se":0.5452365958989239},"retail":{"n":64,"mean":-34.838943275266416,"se":0.5275565700162362},"arb":{"n":64,"mean":11.268666742336483,"se":0.25081404842339483}},"v2_retail_volume_y_range":[58425.88710375651,93934.40079231845]}}},{"name":"h4d","sha256":"4a6de25d1c91dfcfc19df9825e33f1cc51f340318c951a7424a6ba03fb3a58ac","seed_range_inclusive":[20000,20063],"valid":true,"paired":{"n":64,"mean_diff":-24.020087591380108,"se":0.5782689900490302,"worst":-35.860119298301925,"worst_seed":20060},"checks":{"candidate":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":5.7411853049416095e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.792788553866558e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":7.734143495559692,"v2":13.467012643814087},"gas":{"max_ok":208199,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":241967,"max_ok_all_callbacks":241967,"oog":0,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":64,"candidate":{"total":484.7170136184686,"retail":511.3880468228913,"arb":-26.671033204422482},"v2":{"total":508.73710120984873,"retail":534.8510488788927,"arb":-26.11394766904394},"delta":{"total":{"n":64,"mean":-24.020087591380108,"se":0.5782689900490302},"retail":{"n":64,"mean":-23.463002056001436,"se":0.46157309538339913},"arb":{"n":64,"mean":-0.5570855353785416,"se":0.5329667089170459}},"v2_retail_volume_y_range":[58425.88710375651,93934.40079231845]}}},{"name":"h4e","sha256":"d6be0deeb3b45d2c9899f609cd16529424c1223d2a57e2a871ae4ca3e3f0de05","seed_range_inclusive":[20000,20063],"valid":true,"paired":{"n":64,"mean_diff":-23.978083246579935,"se":0.5799353179734283,"worst":-37.771743037983015,"worst_seed":20060},"checks":{"candidate":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.252776074688882e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":64,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.792788553866558e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":8.265647888183594,"v2":13.467012643814087},"gas":{"max_ok":208200,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":241967,"max_ok_all_callbacks":241967,"oog":0,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":64,"candidate":{"total":484.7590179632688,"retail":519.217029850424,"arb":-34.458011887155074},"v2":{"total":508.73710120984873,"retail":534.8510488788927,"arb":-26.11394766904394},"delta":{"total":{"n":64,"mean":-23.978083246579935,"se":0.5799353179734283},"retail":{"n":64,"mean":-15.634019028468693,"se":0.4253922821209288},"arb":{"n":64,"mean":-8.344064218111134,"se":0.716032357024203}},"v2_retail_volume_y_range":[58425.88710375651,93934.40079231845]}}}],"ablation":{"h1_name":"h1","h4_name":"h4a","n":64,"h1_minus_h4_mean_diff":0.0,"h1_minus_h4_se":0.0,"bit_identical_submission_edges_and_counters":true,"same_selected_policy":true,"interpretation":"At these priors/action levels the horizon did not alter the chosen policy; no measured H4 benefit over H1."},"top2":[{"name":"h4a","sha256":"2e0d6b44b102b1ceacc689aec0c712b9558718bdde0b4b365f4bf39275609978","seed_range_inclusive":[22000,22255],"valid":true,"paired":{"n":256,"mean_diff":-24.312551585811732,"se":0.27075836424224237,"worst":-37.3349322162025,"worst_seed":22199},"checks":{"candidate":{"n":256,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":7.617018127348274e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":256,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.139089236967266e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":27.907583951950073,"v2":43.613609313964844},"gas":{"max_ok":210519,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":243605,"max_ok_all_callbacks":243605,"oog":3,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":256,"candidate":{"total":502.97113748846795,"retail":518.962026872053,"arb":-15.99088938358518},"v2":{"total":527.2836890742797,"retail":554.2800416146457,"arb":-26.996352540366107},"delta":{"total":{"n":256,"mean":-24.312551585811732,"se":0.27075836424224237},"retail":{"n":256,"mean":-35.31801474259264,"se":0.2814786297803442},"arb":{"n":256,"mean":11.005463156780927,"se":0.09091610788330404}},"v2_retail_volume_y_range":[59118.12245154398,95390.39691206992]}}},{"name":"h4e","sha256":"d6be0deeb3b45d2c9899f609cd16529424c1223d2a57e2a871ae4ca3e3f0de05","seed_range_inclusive":[22000,22255],"valid":true,"paired":{"n":256,"mean_diff":-24.92180251537467,"se":0.31604468466462876,"worst":-42.937540978251945,"worst_seed":22244},"checks":{"candidate":{"n":256,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.821210263296962e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":256,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":6.139089236967266e-12,"normalizer_oog":0,"normalizer_other_errors":0}},"seconds":{"candidate":32.15975499153137,"v2":43.613609313964844},"gas":{"max_ok":210581,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0},"v2_gas":{"max_ok":243605,"max_ok_all_callbacks":243605,"oog":3,"other_errors":0},"actual_edge_decomposition":{"overall":{"n":256,"candidate":{"total":502.36188655890504,"retail":538.718981206376,"arb":-36.35709464747113},"v2":{"total":527.2836890742797,"retail":554.2800416146457,"arb":-26.996352540366107},"delta":{"total":{"n":256,"mean":-24.92180251537467,"se":0.31604468466462876},"retail":{"n":256,"mean":-15.561060408269595,"se":0.19947256194975363},"arb":{"n":256,"mean":-9.360742107105025,"se":0.3623602858379534}},"v2_retail_volume_y_range":[59118.12245154398,95390.39691206992]}}}],"freeze":{"name":"h4a","sha256":"2e0d6b44b102b1ceacc689aec0c712b9558718bdde0b4b365f4bf39275609978","confirmation_seeds_inclusive":[4270000,4271999],"rule":"Frozen before either confirmation run. No code or table changes and no confirmation reuse."},"paired":{"n":2000,"mean_diff":-23.680271672164476,"se":0.09861307487312405,"worst":-89.58930863432988,"worst_seed":4271883},"gas":{"max_ok":212593,"max_ok_all_callbacks":220941,"oog":0,"other_errors":0,"by_callback":{"afterInitialize":{"calls":2000,"ok":2000,"max_ok_gas":220941,"sum_ok_gas":441882000,"oog":0,"revert":0,"other_halt":0,"tx_error":0,"bad_return":0},"afterSwap":{"calls":11686872,"ok":11686872,"max_ok_gas":212593,"sum_ok_gas":1174019537479,"oog":0,"revert":0,"other_halt":0,"tx_error":0,"bad_return":0},"getName":{"calls":2000,"ok":2000,"max_ok_gas":21554,"sum_ok_gas":43108000,"oog":0,"revert":0,"other_halt":0,"tx_error":0,"bad_return":0}}},"v2_gas":{"max_ok":244149,"max_ok_all_callbacks":244149,"oog":45,"other_errors":0,"by_callback":{"afterInitialize":{"calls":2000,"ok":2000,"max_ok_gas":236377,"sum_ok_gas":472754000,"oog":0,"revert":0,"other_halt":0,"tx_error":0,"bad_return":0},"afterSwap":{"calls":20714286,"ok":20714241,"max_ok_gas":244149,"sum_ok_gas":2307351651122,"oog":45,"revert":0,"other_halt":0,"tx_error":0,"bad_return":0},"getName":{"calls":2000,"ok":2000,"max_ok_gas":21545,"sum_ok_gas":43090000,"oog":0,"revert":0,"other_halt":0,"tx_error":0,"bad_return":0}}},"actual_retail_arb_deltas":{"overall":{"n":2000,"candidate":{"total":504.8732253101126,"retail":521.8820786997178,"arb":-17.0088533896052},"v2":{"total":528.5534969822771,"retail":556.6084204500604,"arb":-28.05492346778328},"delta":{"total":{"n":2000,"mean":-23.680271672164476,"se":0.09861307487312405},"retail":{"n":2000,"mean":-34.72634175034256,"se":0.09214662144038732},"arb":{"n":2000,"mean":11.046070078178078,"se":0.04202292702239492}},"v2_retail_volume_y_range":[53296.69903343661,98684.91086880988]},"low":{"n":667,"candidate":{"total":411.39697838145554,"retail":424.8834317895197,"arb":-13.486453408064206},"v2":{"total":433.6787621309269,"retail":458.27746941091635,"arb":-24.59870727998947},"delta":{"total":{"n":667,"mean":-22.28178374947137,"se":0.15219051910090256},"retail":{"n":667,"mean":-33.39403762139662,"se":0.15271025289994555},"arb":{"n":667,"mean":11.112253871925265,"se":0.05110270974796728}},"v2_retail_volume_y_range":[53296.69903343661,71219.19972475462]},"middle":{"n":667,"candidate":{"total":502.5439040514543,"retail":518.8956025526438,"arb":-16.351698501189556},"v2":{"total":526.5920515267713,"retail":553.9894118594575,"arb":-27.397360332686077},"delta":{"total":{"n":667,"mean":-24.0481474753171,"se":0.18038798810557682},"retail":{"n":667,"mean":-35.093809306813675,"se":0.15128434952745953},"arb":{"n":667,"mean":11.045661831496519,"se":0.09767639768291508}},"v2_retail_volume_y_range":[71226.68929129685,82273.72862318609]},"high":{"n":666,"candidate":{"total":600.8226457019135,"retail":622.0173295693882,"arb":-21.194683867474684},"v2":{"total":625.5350769592634,"retail":657.7099565957678,"arb":-32.17487963650446},"delta":{"total":{"n":666,"mean":-24.712431257349913,"se":0.1648136439473698},"retail":{"n":666,"mean":-35.692627026379675,"se":0.16131292164433178},"arb":{"n":666,"mean":10.980195769029772,"se":0.06114989019207562}},"v2_retail_volume_y_range":[82303.9611668591,98684.91086880988]}},"confirmation_checks":{"candidate":{"n":2000,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":9.492850949754938e-12,"normalizer_oog":0,"normalizer_other_errors":0},"v2":{"n":2000,"all_chunks_complete":true,"counters_per_seed_match_global":true,"max_abs_reconciliation_error":1.5006662579253316e-11,"normalizer_oog":0,"normalizer_other_errors":0}},"confirmation_seconds":{"candidate":230.91566848754883,"v2":385.87186646461487},"model_checks":{"arb_random_cases":100000,"max_abs_k_error":2.3283064365386963e-10,"max_abs_band_relative_error":4.440892098500626e-16,"router_share_cases":9,"max_abs_share_error":4.191091917959966e-13},"measurement_evidence":{"type":"Locally measured outputs from supplied instrumented H harness; not independently certified.","confirmation_candidate_rows_sha256":"d5ee0c5cf07ea14adcb4d4c65b8e8c143bdac882c6faf21307470cd5c81f56df","confirmation_v2_rows_sha256":"551a0de3f0286bb100592a606eefe0bf0074a469b085127927a6403f01367450","experiment_driver":"import sys,json,time,hashlib,math\nfrom pathlib import Path\nimport numpy as np\nimport amm_sim_rs\nimport harness as H\n\n# Preserve original validated harness accounting, adding observed retail volume.\ndef run(name,s0,s1,out):\n src,bc=H.compile_src('../V2.sol' if name=='V2' else 'scratch/'+name+'.sol')\n vanilla=list(H.get_vanilla_bytecode_and_abi()[0]);cfgs=H.build_configs(s0,s1)\n t=time.time();rows={};summaries=[]\n for i in range(0,len(cfgs),8):\n  part=cfgs[i:i+8]\n  # harness.run calls run_batch separately against Vanilla at 8 workers.\n  summary,rr=H.run(name,bc,vanilla,part,chunk=8)\n  summaries.append(summary);rows.update(rr)\n  Path(out).write_text(json.dumps({'name':name,'sha256':hashlib.sha256(src.encode()).hexdigest(),'n':len(rows),'seconds':time.time()-t,'chunks':summaries,'rows':rows}))\n  print(name,len(rows),'seconds',round(time.time()-t,2),'oog',sum(s['gas']['submission']['oog'] for s in summaries),flush=True)\n  assert summary['complete'] and summary['counters_per_seed_match_global']\n  assert summary['max_abs_reconciliation_error']<1e-8\n  assert summary['gas']['submission']['other_errors']==0\n  assert summary['gas']['normalizer']['other_errors']==0 and summary['gas']['normalizer']['oog']==0\n return rows\nif __name__=='__main__':run(sys.argv[1],int(sys.argv[2]),int(sys.argv[3]),sys.argv[4])\n","comparison_and_aggregation":"import json,math,hashlib,statistics\nfrom pathlib import Path\nCALLBACKS=('afterInitialize','afterSwap','getName')\ndef load(path):return json.loads(Path(path).read_text())\ndef stat(xs):\n n=len(xs);return {'n':n,'mean':statistics.mean(xs),'se':statistics.stdev(xs)/math.sqrt(n) if n>1 else 0.}\ndef gas(ds,role='submission'):\n by={}\n for cb in CALLBACKS:\n  records=[ch['gas'][role]['by_callback'][cb] for ch in ds['chunks']]\n  by[cb]={k:(max(r[k] for r in records) if k=='max_ok_gas' else sum(r[k] for r in records)) for k in records[0]}\n return {'max_ok':by['afterSwap']['max_ok_gas'],'max_ok_all_callbacks':max(r['max_ok_gas'] for r in by.values()),'oog':sum(r['oog'] for r in by.values()),'other_errors':sum(r[k] for r in by.values() for k in ('revert','other_halt','tx_error','bad_return')),'by_callback':by}\ndef checks(ds):\n return {'n':ds['n'],'all_chunks_complete':all(c['complete'] for c in ds['chunks']),'counters_per_seed_match_global':all(c['counters_per_seed_match_global'] for c in ds['chunks']),'max_abs_reconciliation_error':max(c['max_abs_reconciliation_error'] for c in ds['chunks']),'normalizer_oog':gas(ds,'normalizer')['oog'],'normalizer_other_errors':gas(ds,'normalizer')['other_errors']}\ndef compare(a,b):\n assert a['n']==b['n'] and set(a['rows'])==set(b['rows'])\n seeds=sorted(a['rows'],key=int);ar=a['rows'];br=b['rows'];d=[ar[s]['submission']['total']-br[s]['submission']['total'] for s in seeds];st=stat(d);wi=min(range(len(d)),key=lambda i:d[i]);ga=gas(a);gb=gas(b);ca=checks(a);cb=checks(b)\n valid=all(c['all_chunks_complete'] and c['counters_per_seed_match_global'] and c['max_abs_reconciliation_error']<1e-8 and c['normalizer_oog']==0 and c['normalizer_other_errors']==0 for c in (ca,cb)) and ga['other_errors']==0 and gb['other_errors']==0 and ga['oog']<=gb['oog']\n groups=[('overall',seeds)]\n if all('retail_volume_y' in br[s] for s in seeds):\n  ordered=sorted(seeds,key=lambda s:(br[s]['retail_volume_y']['submission'],int(s)));n=len(seeds)\n  groups += [(name,ordered[lo:hi]) for name,lo,hi in [('low',0,(n+2)//3),('middle',(n+2)//3,(2*n+2)//3),('high',(2*n+2)//3,n)]]\n decomp={}\n for name,ss in groups:\n  decomp[name]={'n':len(ss),'candidate':{},'v2':{},'delta':{}}\n  for k in ('total','retail','arb'):\n   decomp[name]['candidate'][k]=statistics.mean(ar[s]['submission'][k] for s in ss)\n   decomp[name]['v2'][k]=statistics.mean(br[s]['submission'][k] for s in ss)\n   decomp[name]['delta'][k]=stat([ar[s]['submission'][k]-br[s]['submission'][k] for s in ss])\n  if 'retail_volume_y' in br[ss[0]]:\n   decomp[name]['v2_retail_volume_y_range']=[min(br[s]['retail_volume_y']['submission'] for s in ss),max(br[s]['retail_volume_y']['submission'] for s in ss)]\n return {'name':a['name'],'sha256':a['sha256'],'seed_range_inclusive':[int(seeds[0]),int(seeds[-1])],'valid':valid,'paired':{'n':st['n'],'mean_diff':st['mean'],'se':st['se'],'worst':d[wi],'worst_seed':int(seeds[wi])},'gas':ga,'v2_gas':gb,'checks':{'candidate':ca,'v2':cb},'seconds':{'candidate':a['seconds'],'v2':b['seconds']},'actual_edge_decomposition':decomp}\n","harness_delta_from_H":"In H.source_files scratch/harness.py, replace row = {\"seed\": r.seed, \"dup\": r.seed in rows} with row = {\"seed\": r.seed, \"dup\": r.seed in rows, \"retail_volume_y\": dict(r.retail_volume_y)}. All accounting, gas and result extraction logic otherwise unchanged."},"blocked":null,"summary":"Frozen H4 table vs V2 on 2000 fresh seeds: mean delta -23.680272, SE 0.098613; candidate OOG 0, V2 OOG 45. Do not replace V2 with this policy."}
