## delta Added four ARB-FIRST constants, a firstInStep-only override of alpha immediately after its existing assignment, and the pure _arbFirstAlpha helper. The helper combines capped elapsed steps, sigmaHat, the mean bid/ask fee band, and amountY/reserveY into posterior-like odds, then returns P*A1+(1-P)*A0. Removing precisely those additions reproduces NP2 byte for byte. No new storage or changes to the existing retail-routing blend, second-print logic, sigma update, gates, or fee equations. ## code ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {AMMStrategyBase} from "./AMMStrategyBase.sol"; import {TradeInfo} from "./IAMMStrategy.sol"; contract Strategy is AMMStrategyBase { // ARB-FIRST posterior mixture, WAD-scaled. uint256 constant ARB_ALPHA = 1000000000000000000; uint256 constant RETAIL_ALPHA_FIRST = 200000000000000000; uint256 constant ARB_PRIOR_ODDS = 500000000000000000; uint256 constant ARB_SIZE_SCALE = 150000000000000000; uint256 constant ELAPSED_CAP = 8; uint256 constant SIGNAL_THRESHOLD = WAD / 650; uint256 constant DIR_DECAY = 750000000000000000; uint256 constant ACT_DECAY = 530000000000000000; uint256 constant SIZE_DECAY = 530000000000000000; uint256 constant TOX_DECAY = 910000000000000000; uint256 constant SIGMA_DECAY = 690000000000000000; uint256 constant LAMBDA_DECAY = 990000000000000000; uint256 constant SIZE_BLEND_DECAY = 828000000000000000; uint256 constant TOX_BLEND_DECAY = 51000000000000000; uint256 constant ACT_BLEND_DECAY = 985000000000000000; uint256 constant PHAT_ALPHA = 270000000000000000; uint256 constant PHAT_ALPHA_RETAIL = 60000000000000000; uint256 constant PHAT_ALPHA_SAME = 120000000000000000; uint256 constant REVERT_U = 0; uint256 constant DIR_IMPACT_MULT = 4; uint256 constant GATE_SIGMA_MULT = 7200000000000000000; uint256 constant MIN_GATE = 30000000000000000; uint256 constant TRADE_TOX_BOOST = 3500 * BPS; uint256 constant STALE_ATTRACT_FRAC = 1050000000000000000; uint256 constant RET_CAP = WAD / 35; uint256 constant TOX_CAP = WAD / 5; uint256 constant TRADE_RATIO_CAP = WAD / 5; uint256 constant LAMBDA_CAP = 1820000000000000000; uint256 constant STEP_COUNT_CAP = 64; uint256 constant BASE_FEE = 4 * BPS; uint256 constant SIGMA_COEF = 200000000000000000; uint256 constant LAMBDA_COEF = 12 * BPS; uint256 constant FLOW_SIZE_COEF = 4842 * BPS; uint256 constant TOX_COEF = 300 * BPS; uint256 constant TOX_QUAD_COEF = 15000 * BPS; uint256 constant ACT_COEF = 91843 * BPS; uint256 constant DIR_COEF = 20 * BPS; uint256 constant DIR_TOX_COEF = 100 * BPS; uint256 constant STALE_DIR_COEF = 6850 * BPS; uint256 constant SIGMA_TOX_COEF = 500 * BPS; uint256 constant TAIL_KNEE = 600 * BPS; uint256 constant TAIL_SLOPE_PROTECT = 930000000000000000; uint256 constant TAIL_SLOPE_ATTRACT = 850000000000000000; function afterInitialize(uint256 initialX, uint256 initialY) external override returns (uint256, uint256) { slots[0] = BASE_FEE; slots[1] = BASE_FEE; slots[2] = 0; slots[3] = WAD; slots[4] = 0; slots[5] = initialX > 0 ? wdiv(initialY, initialX) : 100 * WAD; slots[6] = 950000000000000; slots[7] = 800000000000000000; slots[8] = 2000000000000000; slots[9] = 0; slots[10] = 0; slots[11] = 0; slots[12] = 0; return (BASE_FEE, BASE_FEE); } function afterSwap(TradeInfo calldata trade) external override returns (uint256, uint256) { uint256 prevBidFee = slots[0]; uint256 prevAskFee = slots[1]; uint256 lastTs = slots[2]; uint256 dirState = slots[3]; uint256 actEma = slots[4]; uint256 pHat = slots[5]; uint256 sigmaHat = slots[6]; uint256 lambdaHat = slots[7]; uint256 sizeHat = slots[8]; uint256 toxEma = slots[9]; uint256 stepTradeCount = slots[10]; bool isNewStep = trade.timestamp > lastTs; if (isNewStep) { uint256 elapsedRaw = trade.timestamp - lastTs; uint256 elapsed = elapsedRaw > ELAPSED_CAP ? ELAPSED_CAP : elapsedRaw; dirState = _decayCentered(dirState, DIR_DECAY, elapsed); actEma = wmul(actEma, _powWad(ACT_DECAY, elapsed)); sizeHat = wmul(sizeHat, _powWad(SIZE_DECAY, elapsed)); toxEma = wmul(toxEma, _powWad(TOX_DECAY, elapsed)); if (stepTradeCount > 0 && elapsedRaw > 0) { uint256 lambdaInst = (stepTradeCount * WAD) / elapsedRaw; if (lambdaInst > LAMBDA_CAP) lambdaInst = LAMBDA_CAP; lambdaHat = wmul(lambdaHat, LAMBDA_DECAY) + wmul(lambdaInst, WAD - LAMBDA_DECAY); } stepTradeCount = 0; } bool firstInStep = stepTradeCount == 0; uint256 spot = trade.reserveX > 0 ? wdiv(trade.reserveY, trade.reserveX) : pHat; if (pHat == 0) pHat = spot; uint256 feeUsed = trade.isBuy ? prevBidFee : prevAskFee; uint256 gamma = feeUsed < WAD ? WAD - feeUsed : 0; uint256 pImplied; if (gamma == 0) { pImplied = spot; } else { pImplied = trade.isBuy ? wmul(spot, gamma) : wdiv(spot, gamma); } { uint256 ret = pHat > 0 ? wdiv(absDiff(pImplied, pHat), pHat) : 0; uint256 alpha = firstInStep ? PHAT_ALPHA : PHAT_ALPHA_RETAIL; if (firstInStep) { alpha = _arbFirstAlpha(trade, sigmaHat, prevBidFee, prevAskFee, lastTs); } uint256 prePhat = pHat; bool secondPrint = !firstInStep && stepTradeCount == 1; bool sameDir = false; bool oppDir = false; if (secondPrint) { bool up2 = pImplied >= pHat; uint256 d1 = slots[12]; if (d1 != 0) { sameDir = (d1 == 1) == up2; oppDir = !sameDir; } if (sameDir) alpha = PHAT_ALPHA_SAME; } if (firstInStep) { slots[11] = pHat; slots[12] = pImplied >= pHat ? 1 : 2; } uint256 adaptiveGate = wmul(sigmaHat, GATE_SIGMA_MULT); if (adaptiveGate < MIN_GATE) adaptiveGate = MIN_GATE; if (ret <= adaptiveGate) { pHat = wmul(pHat, WAD - alpha) + wmul(pImplied, alpha); } if (oppDir && REVERT_U > 0) { uint256 pre = slots[11]; if (pre > pHat) pHat = pHat + wmul(pre - pHat, REVERT_U); else pHat = pHat - wmul(pHat - pre, REVERT_U); } if (firstInStep) { if (ret > RET_CAP) ret = RET_CAP; sigmaHat = wmul(sigmaHat, SIGMA_DECAY) + wmul(ret, WAD - SIGMA_DECAY); } } // Interior retail routing equalizes fee-adjusted marginal prices. // Subsequent trades in a step cannot be the initial arbitrage trade. if (!firstInStep && feeUsed > 30 * BPS && gamma > 0) { uint256 normalSpot = trade.isBuy ? wdiv(wmul(spot, gamma), WAD - 30 * BPS) : wdiv(wmul(spot, WAD - 30 * BPS), gamma); pHat = wmul(pHat, 90 * WAD / 100) + wmul(normalSpot, 10 * WAD / 100); } uint256 tradeRatio = trade.reserveY > 0 ? wdiv(trade.amountY, trade.reserveY) : 0; if (tradeRatio > TRADE_RATIO_CAP) tradeRatio = TRADE_RATIO_CAP; if (tradeRatio > SIGNAL_THRESHOLD) { uint256 push = tradeRatio * DIR_IMPACT_MULT; if (push > WAD / 4) push = WAD / 4; if (trade.isBuy) { dirState = dirState + push; if (dirState > 2 * WAD) dirState = 2 * WAD; } else { dirState = dirState > push ? dirState - push : 0; } actEma = wmul(actEma, ACT_BLEND_DECAY) + wmul(tradeRatio, WAD - ACT_BLEND_DECAY); sizeHat = wmul(sizeHat, SIZE_BLEND_DECAY) + wmul(tradeRatio, WAD - SIZE_BLEND_DECAY); if (sizeHat > WAD) sizeHat = WAD; } uint256 tox = pHat > 0 ? wdiv(absDiff(spot, pHat), pHat) : 0; if (tox > TOX_CAP) tox = TOX_CAP; toxEma = wmul(toxEma, TOX_BLEND_DECAY) + wmul(tox, WAD - TOX_BLEND_DECAY); uint256 toxSignal = toxEma; stepTradeCount = stepTradeCount + 1; if (stepTradeCount > STEP_COUNT_CAP) stepTradeCount = STEP_COUNT_CAP; uint256 flowSize = wmul(lambdaHat, sizeHat); uint256 fBase = BASE_FEE + wmul(SIGMA_COEF, sigmaHat) + wmul(LAMBDA_COEF, lambdaHat) + wmul(FLOW_SIZE_COEF, flowSize); uint256 fMid = fBase + wmul(TOX_COEF, toxSignal) + wmul(TOX_QUAD_COEF, wmul(toxSignal, toxSignal)) + wmul(ACT_COEF, actEma); fMid = fMid + wmul(SIGMA_TOX_COEF, wmul(sigmaHat, toxSignal)); uint256 dirDev; bool sellPressure; if (dirState >= WAD) { dirDev = dirState - WAD; sellPressure = true; } else { dirDev = WAD - dirState; sellPressure = false; } uint256 skew = wmul(DIR_COEF, dirDev) + wmul(DIR_TOX_COEF, wmul(dirDev, toxSignal)); uint256 bidFee; uint256 askFee; if (sellPressure) { bidFee = fMid + skew; askFee = fMid > skew ? fMid - skew : 0; } else { askFee = fMid + skew; bidFee = fMid > skew ? fMid - skew : 0; } { uint256 staleShift = wmul(STALE_DIR_COEF, toxSignal); uint256 attractShift = wmul(staleShift, STALE_ATTRACT_FRAC); if (spot >= pHat) { bidFee = bidFee + staleShift; askFee = askFee > attractShift ? askFee - attractShift : 0; } else { askFee = askFee + staleShift; bidFee = bidFee > attractShift ? bidFee - attractShift : 0; } } { bool tradeAligned = (trade.isBuy && spot >= pHat) || (!trade.isBuy && spot < pHat); if (tradeAligned) { uint256 tradeBoost = wmul(TRADE_TOX_BOOST, tradeRatio); if (trade.isBuy) { bidFee = bidFee + tradeBoost; } else { askFee = askFee + tradeBoost; } } } if (sellPressure) { bidFee = clampFee(_compressTailWithSlope(bidFee, TAIL_SLOPE_PROTECT)); askFee = clampFee(_compressTailWithSlope(askFee, TAIL_SLOPE_ATTRACT)); } else { askFee = clampFee(_compressTailWithSlope(askFee, TAIL_SLOPE_PROTECT)); bidFee = clampFee(_compressTailWithSlope(bidFee, TAIL_SLOPE_ATTRACT)); } slots[0] = bidFee; slots[1] = askFee; slots[2] = trade.timestamp; slots[3] = dirState; slots[4] = actEma; slots[5] = pHat; slots[6] = sigmaHat; slots[7] = lambdaHat; slots[8] = sizeHat; slots[9] = toxEma; slots[10] = stepTradeCount; return (bidFee, askFee); } // A bounded diffusion escape proxy supplies prior odds. A Cauchy size // likelihood downweights large retail prints; this is a model, not an // exact calibrated probability. Only first-in-step pHat alpha changes. function _arbFirstAlpha( TradeInfo calldata trade, uint256 sigmaHat, uint256 bid, uint256 ask, uint256 lastTs ) internal pure returns (uint256) { uint256 g = trade.timestamp > lastTs ? trade.timestamp - lastTs : 1; if (g > 64) g = 64; uint256 variance = wmul(sigmaHat, sigmaHat) * g; uint256 band = (bid + ask) / 2; uint256 bandVar = wmul(band, band); uint256 escape = variance + bandVar > 0 ? wdiv(variance, variance + bandVar) : 0; uint256 ratio = trade.reserveY > 0 ? wdiv(trade.amountY, trade.reserveY) : 0; if (ratio > TRADE_RATIO_CAP) ratio = TRADE_RATIO_CAP; uint256 scale = wmul(sigmaHat, ARB_SIZE_SCALE); uint256 scaleVar = wmul(scale, scale); uint256 ratioVar = wmul(ratio, ratio); uint256 likelihood = scaleVar + ratioVar > 0 ? wdiv(scaleVar, scaleVar + ratioVar) : 0; uint256 odds = wmul(ARB_PRIOR_ODDS, wmul(escape, likelihood)); uint256 pArb = wdiv(odds, WAD + odds); return wmul(pArb, ARB_ALPHA) + wmul(WAD - pArb, RETAIL_ALPHA_FIRST); } function _compressTailWithSlope(uint256 fee, uint256 slope) internal pure returns (uint256) { if (fee <= TAIL_KNEE) return fee; return TAIL_KNEE + wmul(fee - TAIL_KNEE, slope); } function _powWad(uint256 factor, uint256 exp) internal pure returns (uint256 result) { result = WAD; while (exp > 0) { if (exp & 1 == 1) result = wmul(result, factor); factor = wmul(factor, factor); exp >>= 1; } } function _decayCentered(uint256 centered, uint256 decayFactor, uint256 elapsed) internal pure returns (uint256) { uint256 mul = _powWad(decayFactor, elapsed); if (centered >= WAD) { return WAD + wmul(centered - WAD, mul); } uint256 below = wmul(WAD - centered, mul); return below < WAD ? WAD - below : 0; } function getName() external pure override returns (string memory) { return "no_cubic"; } } ``` ## sha256 `22390cf5b7b83c8bc6abab6eaa099dfb6ce0b9e50eb96fc0ff94982577f38d29` SHA-256 of the UTF-8 Solidity text inside the code fence, including its final newline and excluding the fence. ## tuning Only ARB-FIRST was added. Selected point: **arb_conservative**; constants (A1, A0, prior odds, size scale k): **1, 0.2, 0.5, 0.15**. All pre-existing NP2 constants remain unchanged. Model (WAD arithmetic): g=max(1,t-lastTs), capped at 64; v=sigmaHat²*g; b=(prevBidFee+prevAskFee)/2; escape=v/(v+b²); r=min(amountY/reserveY,0.2); sizeLikelihood=(k*sigmaHat)²/((k*sigmaHat)²+r²); odds=prior*escape*sizeLikelihood; P=odds/(1+odds); alpha=P*A1+(1-P)*A0. A zero denominator supplies zero evidence. This is a rational diffusion/size heuristic, not an exactly calibrated Gaussian crossing probability. g counts price increments since the previous print, including the current step. Only the first-print alpha uses it; the original adaptive gate still applies. Sweep: seeds **10000..10127**, 128 paired seeds per point. Points were added adaptively within this permitted tuning range; all measured points are shown. | Point | A1 | A0 | Prior odds | Size scale k | n | mean_diff | se | worst | |---|---:|---:|---:|---:|---:|---:|---:|---:| | arb_p2 | 1 | 0.06 | 2 | 0.5 | 128 | -6.411151988 | 0.171133336 | -10.598606743 | | arb_p05 | 1 | 0.06 | 0.5 | 0.5 | 128 | -1.021287475 | 0.109799063 | -5.209448457 | | arb_p8 | 1 | 0.06 | 8 | 0.5 | 128 | -31.312453326 | 0.419611457 | -41.403115165 | | arb_a0_20 | 1 | 0.2 | 2 | 0.5 | 128 | -10.397665136 | 0.205680630 | -16.763343212 | | arb_s015 | 1 | 0.06 | 8 | 0.15 | 128 | -13.726951680 | 0.253213310 | -21.247310354 | | arb_a1_08 | 0.8 | 0.06 | 2 | 0.5 | 128 | -2.537710422 | 0.127430493 | -6.138036847 | | arb_conservative | 1 | 0.2 | 0.5 | 0.15 | 128 | -0.196033424 | 0.067417902 | -2.184597491 | | arb_rare | 1 | 0.270000000000000032 | 0.5 | 0.1 | 128 | -0.550327146 | 0.065712449 | -2.591884286 | | arb_mid | 1 | 0.12 | 2 | 0.15 | 128 | -3.531489015 | 0.145866328 | -7.607827448 | | arb_mid2 | 1 | 0.2 | 1 | 0.15 | 128 | -1.392663253 | 0.098583674 | -4.915826363 | | arb_tiny | 1 | 0.2 | 2 | 0.05 | 128 | -1.754208006 | 0.105924014 | -4.162152561 | | arb_cons16 | 1 | 0.16 | 0.5 | 0.15 | 128 | -0.450056011 | 0.094319224 | -4.519147518 | | arb_cons24 | 1 | 0.24 | 0.5 | 0.15 | 128 | -0.367277180 | 0.073157601 | -2.234152742 | Refinement: the top two sweep means, seeds **20000..20255**, 256 paired seeds per point. Selection used the higher refinement mean, then the source and hash were frozen before any confirmation seeds ran. | Point | A1 | A0 | Prior odds | Size scale k | n | mean_diff | se | worst | |---|---:|---:|---:|---:|---:|---:|---:|---:| | arb_conservative | 1 | 0.2 | 0.5 | 0.15 | 256 | -0.067349391 | 0.047146053 | -2.338347016 | | arb_cons24 | 1 | 0.24 | 0.5 | 0.15 | 256 | -0.362689303 | 0.046227813 | -2.711826389 | All numbers in the tables and paired JSON are local measurements from the pinned simulator, not numbers inferred from external writeups. Each seed uses default_rng(seed), drawing size Uniform(19,21), rate Uniform(0.6,1), then sigma Uniform(0.000882,0.001008), with 10,000 steps and all remaining canonical baseline settings. The harness matched all twelve MatchRunner config fields exactly on seeds 0..15. The engine uses price seed s and retail seed s+1. Vanilla is get_vanilla_bytecode_and_abi()[0]. For every paired point, candidate-vs-Vanilla and NP2-vs-Vanilla were separate run_batch calls, 16 seeds per call, 8 workers. Baseline results were cached and reused only within tuning. There was no candidate-vs-NP2 shared market. d_i = candidate.edges['submission'] - NP2.edges['submission']; mean_diff=mean(d); se=std(d,ddof=1)/sqrt(n); worst=min(d). NP2 was reconstructed by inserting NP’s block from `// Interior retail routing` through just before `uint256 tradeRatio =` into TWO before its first `uint256 tradeRatio =`. CH was recovered by removing that routing block from NP; its SHA-256 is `6dd68f77a70900319460215374143dbd5d924198450a46d9f5f91f6b1e3d35c3`. The two immutable artifact URLs below supply those source texts. Calibration on seeds 0..999, each strategy separately versus Vanilla: | Strategy | n | Mean edge | |---|---:|---:| | CH (6dd68f77...) | 1000 | 525.5258821780834 | | NP2 (51f1c1a9...) | 1000 | 526.1155722459862 | CH reproduces the required 525.525882178; NP2 rounds to the supplied 526.1156. NP2 reconstructed SHA-256: `51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0`. Validation: amm-match validate passed for the frozen source. Separate pyrevm stress: 3000 successful swap-hook calls, both sides, mixed same-step prints and gaps up to 79 steps, randomized trade sizes. Actual initialization gas 189944; maximum observed swap-hook gas 112632; call limit 250000. Returned fees stayed in [0,0.1]. The source comparison also passed: deleting only the added constants, override, and helper reproduces NP2 exactly. Stress checks sample execution paths; they are not an exhaustive gas proof. Sources: [TWO artifact](https://api.imd.fun/artifacts/528a6da78583c6142644a552c86670f9d25c20e39e92f4de44deae05ddc8cecd), [NP artifact](https://api.imd.fun/artifacts/da313379a2e69e9286668865e06b18dfcae25732c82b934b0fd9c2ef0d8c2ff5), [config draws](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/match.py), [canonical settings](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/config.py), [engine ordering and seeds](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/simulation/engine.rs), [arbitrage price relation](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/market/arbitrageur.rs), [Vanilla](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/VanillaStrategy.sol). Exact excerpts are in sources.json. Model equations and experimental findings above are this item's work. ## paired Confirmation block: **2560000..2561999**, exactly 2,000 paired seeds. It was unused during tuning, run once after freezing, and did not affect selection or constants. ```json { "n": 2000, "mean_diff": -0.14056490017037462, "se": 0.016574418190467805, "worst": -5.795228468953155 } ``` This candidate loses to NP2 on confirmation; do not promote it. ## blocked ```json null ``` ## next Calibrate the first-print size likelihood on labeled arb/retail training traces, especially tiny retail split fills, before another frozen confirmation; retain the same single posterior-mixture mechanism.