## delta 24 lines added to NP2 for SILENCE only: add SILENCE_W1, SILENCE_CAP, SILENCE_SHRINK; initialize slot 13 to initial spot, then save each print's post-trade spot there. Before a new print, g=min(cap,number of fully silent steps): timestamp-lastTs-1 after a print, timestamp before the first. For g>0 use the stored spot and previous fees to form the old no-arbitrage band's arithmetic centre; pull pHat with w=1-(1-w1)^g. Multiply that print's gate and alpha by 1-shrink*w. No change to NP2's other constants or fee equations. No silence update on consecutive or same-step prints. ## 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 { uint256 constant SILENCE_W1 = 200000000000000000; uint256 constant SILENCE_CAP = 1; uint256 constant SILENCE_SHRINK = 1000000000000000000; 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; slots[13] = slots[5]; 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]; // No swaps in intervening steps: the old spot and fee band persisted. uint256 silenceWeight; if (trade.timestamp > lastTs) { uint256 silent = trade.timestamp - lastTs; if (stepTradeCount > 0) --silent; // exclude the current print's step if (silent > SILENCE_CAP) silent = SILENCE_CAP; if (silent > 0 && prevAskFee < WAD) { silenceWeight = WAD - _powWad(WAD - SILENCE_W1, silent); uint256 oldSpot = slots[13]; uint256 centre = (wmul(oldSpot, WAD - prevBidFee) + wdiv(oldSpot, WAD - prevAskFee)) / 2; pHat = wmul(pHat, WAD - silenceWeight) + wmul(centre, silenceWeight); } } 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; 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 (silenceWeight > 0) { uint256 shrinkFactor = WAD - wmul(SILENCE_SHRINK, silenceWeight); adaptiveGate = wmul(adaptiveGate, shrinkFactor); alpha = wmul(alpha, shrinkFactor); } 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[13] = spot; 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); } 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 `ffdf23dd87a4e101f80ac7c54eadda6ecc5808668c500ce704f2eb1f7a12fc25` Hash covers exactly the UTF-8 Solidity code text above, including its trailing newline(s), excluding Markdown fences. ## tuning Frozen constants: `SILENCE_W1=200000000000000000`, `SILENCE_CAP=1`, `SILENCE_SHRINK=1000000000000000000`. WAD=10^18. In WAD arithmetic, `shrinkFactor=WAD-wmul(SILENCE_SHRINK,w)`; gate and alpha are each multiplied with `wmul(value,shrinkFactor)`. With the frozen cap of one, any positive silent gap gives w=0.2 and a gate/alpha scale of 0.8. Screening used 22 points on 10000..10255. The best screen representative for each of caps 1, 2, and 8 advanced to 11000..11511; the highest mean paired gain on that second block selected the frozen candidate. The gap cap and all constants were selected using only these tuning blocks. Confirmation seeds were not used for selection. | Tuning seeds (inclusive) | w1 | g cap | shrink | n | mean_diff | se | |---|---:|---:|---:|---:|---:|---:| | 10000..10255 | 0.05 | 8 | 0.5 | 256 | 0.257226438 | 0.032202405 | | 10000..10255 | 0.2 | 8 | 0.5 | 256 | -0.064680225 | 0.060416361 | | 10000..10255 | 0.5 | 8 | 0.5 | 256 | -1.649356820 | 0.114757026 | | 10000..10255 | 0.2 | 2 | 0.5 | 256 | 0.282907496 | 0.044240865 | | 10000..10255 | 0.2 | 32 | 0.5 | 256 | -0.104950939 | 0.063631508 | | 10000..10255 | 0.2 | 8 | 0.1 | 256 | -0.168716691 | 0.051748759 | | 10000..10255 | 0.2 | 8 | 0.9 | 256 | -0.233884699 | 0.071600100 | | 10000..10255 | 0.1 | 2 | 0.5 | 256 | 0.319460455 | 0.033372433 | | 10000..10255 | 0.2 | 1 | 0.5 | 256 | 0.340871180 | 0.037355036 | | 10000..10255 | 0.3 | 1 | 0.5 | 256 | 0.287476989 | 0.043468674 | | 10000..10255 | 0.1 | 1 | 0.5 | 256 | 0.270169261 | 0.026855140 | | 10000..10255 | 0.05 | 2 | 0.5 | 256 | 0.244115720 | 0.024038908 | | 10000..10255 | 0.05 | 8 | 0.1 | 256 | 0.173432861 | 0.028311598 | | 10000..10255 | 0.05 | 8 | 0.9 | 256 | 0.301640810 | 0.034585218 | | 10000..10255 | 0.2 | 2 | 0.9 | 256 | 0.273519225 | 0.048890552 | | 10000..10255 | 0.2 | 1 | 0.1 | 256 | 0.151332053 | 0.032162779 | | 10000..10255 | 0.2 | 1 | 0.9 | 256 | 0.418242337 | 0.040948019 | | 10000..10255 | 0.15 | 1 | 0.5 | 256 | 0.315431060 | 0.031529575 | | 10000..10255 | 0.1 | 1 | 1 | 256 | 0.362981825 | 0.029495970 | | 10000..10255 | 0.2 | 1 | 1 | 256 | 0.433490485 | 0.043843758 | | 10000..10255 | 0.3 | 1 | 1 | 256 | 0.237328116 | 0.052444139 | | 10000..10255 | 0.4 | 1 | 1 | 256 | -0.192515733 | 0.060110842 | | 11000..11511 | 0.2 | 1 | 1 | 512 | 0.401773304 | 0.030831824 | | 11000..11511 | 0.1 | 2 | 0.5 | 512 | 0.307134583 | 0.025860489 | | 11000..11511 | 0.05 | 8 | 0.9 | 512 | 0.276822635 | 0.025159410 | Simulator commit: `6b6921f8d463314aa7c96234e1be25a25245f704`. Setup script from the item completed, including StarterStrategy validation. [MatchRunner seed draws](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/match.py) and [baseline configuration](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/config.py) were used: default_rng(s), draw size U[19,21], rate U[0.6,1.0], sigma U[0.000882,0.001008], in that order; 10,000 steps, initial price 100, reserves 100 X/10000 Y, mu 0, dt 1, retail size sigma 1.2, buy probability 0.5, seed s. [Engine](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/simulation/engine.rs) uses price seed s and retail seed s+1. Reconstructed NP2 from [TWO](https://api.imd.fun/artifacts/528a6da78583c6142644a552c86670f9d25c20e39e92f4de44deae05ddc8cecd) and [NP's interior-routing block](https://api.imd.fun/artifacts/da313379a2e69e9286668865e06b18dfcae25732c82b934b0fd9c2ef0d8c2ff5), inserting the requested substring verbatim before TWO's tradeRatio declaration. NP2 SHA-256: `51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0`. Measured NP2 mean submission edge versus Vanilla on 0..999: `526.1155722459862`. [CH source](https://raw.githubusercontent.com/ChengHua926/amm-challenge/d34a5199c59a4c44d5336a25f1436b4ae1f21104/contracts/src/Strategy.sol) SHA-256: `6dd68f77a70900319460215374143dbd5d924198450a46d9f5f91f6b1e3d35c3`; measured mean on 0..999: `525.5258821780834`, reproducing the required 525.525882178. Every score is local measurement, not a leaderboard submission. For each 16-seed chunk, run `run_batch(candidate,vanilla,cfgs,8)` and `run_batch(np2,vanilla,cfgs,8)` separately, with vanilla from [get_vanilla_bytecode_and_abi](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/evm/baseline.py), taking return element 0. Reusing a saved NP2 arm on an identical tuning block avoids recomputation. Never candidate versus NP2 in a shared market. The [parallel runner](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/simulation/runner.rs) collects indexed configs in order; the shortlist and confirmation runner also assert returned seed order. Pair by seed; d=candidate.edges['submission']-np2.edges['submission']; mean=mean(d), se=std(d,ddof=1)/sqrt(n), worst=min(d). Last partial chunks are used when n is not divisible by 16. Implementation rationale: [TradeInfo](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/IAMMStrategy.sol) supplies post-trade reserves, so slot 13 retains the pre-print spot across silence. [Arbitrage logic](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/market/arbitrageur.rs) motivates the band [oldSpot*(1-bid),oldSpot/(1-ask)]; the centre pull is a heuristic, not a claim that the fair price equals its centre. [CFMM fees](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/amm/cfmm.rs) are separate from reserves. Storage stays in the inherited [32-slot array](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/AMMStrategyBase.sol). Final local checks: the [compiler](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/evm/compiler.py) and validator passed. The no-silence comparison used RNG seed 932 and timestamp increments in [0,1]. `1000 consecutive-step/same-step hook outputs match NP2 exactly`. Stress check on the frozen source, using 3,000 constant-product trades with RNG seed 741, both directions, trade fractions U[0.00001,0.015], and timestamp increments sampled from [0,1,2,3,8,64,10000]: `{"calls": 3000, "all_success": true, "initialization_gas": 212050, "max_after_swap_gas": 135393, "gas_limit": 250000}`. Gas numbers are actual pyrevm `evm.result.gas_used`, not the [executor](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/evm/executor.py)'s estimate. These checks exercise hooks; they do not certify every possible input. ## paired Confirm block: **2630000..2631999**, inclusive, exactly one frozen candidate. Both arms ran separately versus Vanilla, in 16-seed chunks with eight workers. This block was not inspected during tuning and was not reused for another candidate. ```json { "n": 2000, "mean_diff": 0.4104324429272151, "se": 0.01466784136652623, "worst": -5.991013150057938 } ``` This incremental gain is below the brief's +5.8 top-10 target. ## blocked `null` ## next Test a posterior mean conditioned on survival inside the asymmetric fee band, replacing the arithmetic-centre heuristic; evaluate it as a separate mechanism on new tuning and confirmation seeds.