# hard-a: hard-cutoff first-print update **Do not promote this candidate.** On the required fresh block, its paired edge difference versus NP2 is **-2.440078 ± 0.033394 SE**, n=2000. The tested mechanism loses despite stale-fee retuning. These are local simulator results, not a leaderboard submission. `blocked = null` `next = retain NP2; reject the tested hard-cutoff implementation. A future experiment could soften the cutoff or relax the imposed weight ranges, using a different fresh confirmation block.` The selected point is T=1.75, wA=0.5, wR=0.1, requiring zero silent steps before the first print, STALE_DIR_COEF=6500*BPS and STALE_ATTRACT_FRAC=1.05*WAD. The first-print ratio uses the **pre-update** sigmaHat and pHat. The original adaptive gate remains in place. Later-print alpha rules and the interior routing observation are unchanged. The unused original PHAT_ALPHA constant is retained to keep the edit small. ## Sources and baseline reconstruction NP2 was reconstructed exactly from [TWO](https://api.imd.fun/artifacts/528a6da78583c6142644a552c86670f9d25c20e39e92f4de44deae05ddc8cecd) by inserting the `// Interior retail routing` block from [NP](https://api.imd.fun/artifacts/da313379a2e69e9286668865e06b18dfcae25732c82b934b0fd9c2ef0d8c2ff5) immediately before TWO's first `uint256 tradeRatio =`, as directed. Its SHA-256 is `51f1c1a9d4999ee460eb8bbc66880da8074b173399a4f5d71f96671482e18ac0`. The simulator checkout was pinned to `6b6921f8d463314aa7c96234e1be25a25245f704`. The supplied item-specific setup script ran once successfully, including Rust release build and StarterStrategy validation. [CH source](https://raw.githubusercontent.com/ChengHua926/amm-challenge/d34a5199c59a4c44d5336a25f1436b4ae1f21104/contracts/src/Strategy.sol) SHA-256 was `6dd68f77a70900319460215374143dbd5d924198450a46d9f5f91f6b1e3d35c3`. Local baseline reproduction on seeds 0–999, before split instrumentation: | Strategy | n | Mean submission edge | Unpaired SE | |---|---:|---:|---:| | CH | 1000 | 525.5258821780834 | 2.7894264590251843 | | NP2 | 1000 | 526.1155722459862 | 2.7896004178197593 | CH matches the required 525.525882178 to the shown rounding. Only the references, not any cutoff candidate, were evaluated on this block. ## Delta: exact edit versus NP2 ```diff --- NP2.sol +++ Strategy.sol @@ -39,7 +39,7 @@ 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 STALE_DIR_COEF = 6500 * BPS; uint256 constant SIGMA_TOX_COEF = 500 * BPS; uint256 constant TAIL_KNEE = 600 * BPS; uint256 constant TAIL_SLOPE_PROTECT = 930000000000000000; @@ -87,7 +87,12 @@ { uint256 ret = pHat > 0 ? wdiv(absDiff(pImplied, pHat), pHat) : 0; - uint256 alpha = firstInStep ? PHAT_ALPHA : PHAT_ALPHA_RETAIL; + uint256 alpha = PHAT_ALPHA_RETAIL; + if (firstInStep) { + bool arbLike = ret <= wmul(sigmaHat, 1750000000000000000); + arbLike = arbLike && trade.timestamp <= lastTs + 1; + alpha = arbLike ? 500000000000000000 : 100000000000000000; + } uint256 prePhat = pHat; bool secondPrint = !firstInStep && stepTradeCount == 1; bool sameDir = false; bool oppDir = false; ``` The gap predicate is `trade.timestamp <= lastTs + 1`: a new print one step after the last observed print has zero silent steps; the initial timestamp-zero print is also eligible. A first print after a larger gap uses wR even if below the ratio cutoff. The cutoff comparison is inclusive and uses fixed-point multiplication, avoiding division by sigmaHat. ## Tuning All 142 initial points used exactly seeds 10000–10079 (n=80 each). Six finalists were extended using only 10080–10255, reusing their saved first 80 observations, so each finalist has **256 distinct tuning seeds**, with no point exceeding 256. All paired comparisons used NP2 as the reference in its own vanilla market. Selection was the highest 256-seed paired mean; confirmation data did not enter selection. Stages: 72 points with T in {0.8,1,1.22,1.5,1.75,2}, wA in {0.5,0.75,1}, wR in {0,0.03,0.06,0.1}; six gap-filtered points; 28 coarse stale-fee points; 36 gap-filtered stale-fee refinements. No tested initial point had positive mean_diff. Frozen selected tuning result: ```json { "point": { "T": 1.75, "A": 0.5, "R": 0.1, "gap": true, "stale": 6500, "attract": 1.05 }, "n": 256, "mean_diff": -2.556071736481814, "se": 0.08879389667734999, "sha256": "0b89253b497d3d6bebfb67d76464ac44c91d07629ede8aa492326118279198dc" } ``` Six finalists, seeds 10000–10255: | T | wA | wR | g=0 required | stale / BPS | attract | n | mean_diff | se | |---:|---:|---:|:---:|---:|---:|---:|---:|---:| | 1.75 | 0.5 | 0.1 | yes | 6500 | 1.05 | 256 | -2.556072 | 0.088794 | | 1.75 | 0.5 | 0.1 | yes | 6500 | 0.8 | 256 | -2.628686 | 0.091547 | | 1.5 | 0.5 | 0.1 | yes | 6500 | 0.8 | 256 | -2.673204 | 0.095044 | | 1.5 | 0.5 | 0.1 | yes | 6500 | 1.05 | 256 | -2.714751 | 0.091336 | | 2 | 0.5 | 0.1 | yes | 6500 | 1.05 | 256 | -2.646200 | 0.085533 | | 2 | 0.5 | 0.1 | yes | 6500 | 0.8 | 256 | -2.793171 | 0.092855 | ## Paired confirmation Candidate bytes were frozen before either confirmation-market run began. Seeds **2780000–2781999** were used once for the frozen candidate, with separate NP2 reference calls. No change or reselection followed confirmation. ```json { "n": 2000, "mean_diff": -2.4400780439910332, "se": 0.03339434477319785, "worst": [ { "seed": 2780300, "diff": -7.315193126152167, "candidate_edge": 683.5123684485734, "np2_edge": 690.8275615747256 }, { "seed": 2780258, "diff": -7.159351351863847, "candidate_edge": 643.5609178298214, "np2_edge": 650.7202691816852 }, { "seed": 2780609, "diff": -7.037453404473581, "candidate_edge": 639.2718606244604, "np2_edge": 646.309314028934 }, { "seed": 2781275, "diff": -7.001182772018865, "candidate_edge": 608.5629592154319, "np2_edge": 615.5641419874507 }, { "seed": 2781435, "diff": -6.877568623894433, "candidate_edge": 484.69025361270997, "np2_edge": 491.5678222366044 } ] } ``` Worst means the five most negative per-seed differences; rows include candidate and NP2 submission edges, not normalizer edge. Mean edge split on the same confirmation block: | Strategy | Arb edge | Retail edge | Total submission edge | |---|---:|---:|---:| | Candidate | -28.632210503 | 547.626746343 | 518.994535840 | | NP2 | -31.221790260 | 552.656404144 | 521.434613884 | | Difference | 2.589579758 | -5.029657802 | -2.440078044 | The maximum absolute per-seed error between arb+retail and total edge across both runs was 8.07176547823e-12, from separate floating-point accumulators. The split describes this local experiment; the task's reported classifier recall, precision and noise RMS were not independently re-estimated here. ## Measurement and checks The config draws follow [MatchRunner._build_configs](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/match.py) and [canonical build_config](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_competition/competition/config.py): for each seed s, `g = numpy.random.default_rng(s)`; draw size U(19,21), then rate U(0.6,1), then sigma U(0.000882,0.001008); call build_config with those values and seed=s. The canonical 10,000-step defaults were used throughout. The pinned [engine](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/simulation/engine.rs) seeds the price process with s and retail with s+1. Every market was submission versus compiled [VanillaStrategy](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/contracts/src/VanillaStrategy.sol) at its fixed 30 BPS. Each `amm_sim_rs.run_batch` call contained at most 20 configs (last partial chunks were smaller), with 8 workers. Candidate and NP2 were never opponents in one market. A seed's difference is candidate submission edge minus NP2 submission edge. Mean is arithmetic; SE is sample SD (`ddof=1`) divided by sqrt(n). Individual normalizer outcomes were not subtracted. The split used a minimal instrumentation patch in the scratch simulator, adding only diagnostic edge-map entries at the existing accumulation sites: ```diff + *edges.entry(format!("{}_arb", arb_result.amm_name)).or_insert(0.0) += -arb_result.profit; let entry = edges.entry(arb_result.amm_name).or_insert(0.0); *entry += -arb_result.profit; ... + *edges.entry(format!("{}_retail", trade.amm_name)).or_insert(0.0) += trade_edge; let entry = edges.entry(trade.amm_name).or_insert(0.0); *entry += trade_edge; ``` No price, routing, RNG, reserve, fee, or original edge calculation was changed. Before using the instrumented build, seeds 0–19 for both CH and NP2 reproduced all 40 original total edges bit-for-bit, and split sums matched within 1e-8. The initial 72-point sweep used the uninstrumented build; gap tests, stale-fee tests, refinements, finalist extensions and confirmation used the instrumented build. Local checks on the frozen code: - `amm-match validate scratch/Strategy.sol`: passed, strategy `no_cubic`. - Six targeted EVM storage assertions passed: first print immediately below cutoff, exactly at cutoff, immediately above cutoff, after a silent step, same-direction second print, and third print. They confirmed alpha values 0.5, 0.5, 0.1, 0.1, 0.12, and 0.06 respectively. - 4,000 randomized constant-product swap-hook stress calls, both directions, same-step prints and gaps of 1, 2, 8, 20, and 100 steps: all succeeded and returned fees in [0, 0.1]. Initialization used 189,944 gas; maximum swap-hook gas was 110,534. These are `pyrevm EVM.result.gas_used` readings, not the Python executor's gas estimates. Both are below the pinned [250,000 hook gas limits](https://raw.githubusercontent.com/benedictbrady/amm-challenge/6b6921f8d463314aa7c96234e1be25a25245f704/amm_sim_rs/src/evm/strategy.rs). This finite stress check is not a proof for arbitrary inputs. - The frozen SHA-256 was checked again after confirmation. No leaderboard action was taken. ## Full tuning log Each section below is n=80 per point on 10000–10079. The finalist table above extends six of these same points to n=256; it does not add another 256 observations to each. ### Cutoff sweep | T | wA | wR | g=0 required | stale / BPS | attract | n | mean_diff | se | |---:|---:|---:|:---:|---:|---:|---:|---:|---:| | 0.8 | 0.5 | 0 | no | 6850 | 1.05 | 80 | -107.291761 | 4.463804 | | 0.8 | 0.5 | 0.03 | no | 6850 | 1.05 | 80 | -39.153273 | 0.912674 | | 0.8 | 0.5 | 0.06 | no | 6850 | 1.05 | 80 | -21.321024 | 0.493622 | | 0.8 | 0.5 | 0.1 | no | 6850 | 1.05 | 80 | -11.153442 | 0.310051 | | 0.8 | 0.75 | 0 | no | 6850 | 1.05 | 80 | -144.508206 | 5.169369 | | 0.8 | 0.75 | 0.03 | no | 6850 | 1.05 | 80 | -57.186877 | 1.168706 | | 0.8 | 0.75 | 0.06 | no | 6850 | 1.05 | 80 | -32.227354 | 0.660234 | | 0.8 | 0.75 | 0.1 | no | 6850 | 1.05 | 80 | -18.526624 | 0.444188 | | 0.8 | 1 | 0 | no | 6850 | 1.05 | 80 | -170.976812 | 5.157587 | | 0.8 | 1 | 0.03 | no | 6850 | 1.05 | 80 | -80.196672 | 2.099801 | | 0.8 | 1 | 0.06 | no | 6850 | 1.05 | 80 | -46.174079 | 0.904509 | | 0.8 | 1 | 0.1 | no | 6850 | 1.05 | 80 | -27.998179 | 0.631762 | | 1 | 0.5 | 0 | no | 6850 | 1.05 | 80 | -106.986765 | 4.946694 | | 1 | 0.5 | 0.03 | no | 6850 | 1.05 | 80 | -34.271789 | 0.895787 | | 1 | 0.5 | 0.06 | no | 6850 | 1.05 | 80 | -18.310587 | 0.490536 | | 1 | 0.5 | 0.1 | no | 6850 | 1.05 | 80 | -9.273851 | 0.309426 | | 1 | 0.75 | 0 | no | 6850 | 1.05 | 80 | -145.309526 | 5.420527 | | 1 | 0.75 | 0.03 | no | 6850 | 1.05 | 80 | -56.294150 | 1.265199 | | 1 | 0.75 | 0.06 | no | 6850 | 1.05 | 80 | -31.414797 | 0.743156 | | 1 | 0.75 | 0.1 | no | 6850 | 1.05 | 80 | -18.826977 | 0.482548 | | 1 | 1 | 0 | no | 6850 | 1.05 | 80 | -178.054070 | 5.536543 | | 1 | 1 | 0.03 | no | 6850 | 1.05 | 80 | -79.335795 | 1.827307 | | 1 | 1 | 0.06 | no | 6850 | 1.05 | 80 | -46.611247 | 1.014592 | | 1 | 1 | 0.1 | no | 6850 | 1.05 | 80 | -30.317926 | 0.657659 | | 1.22 | 0.5 | 0 | no | 6850 | 1.05 | 80 | -57.749563 | 3.471447 | | 1.22 | 0.5 | 0.03 | no | 6850 | 1.05 | 80 | -21.018342 | 0.650900 | | 1.22 | 0.5 | 0.06 | no | 6850 | 1.05 | 80 | -12.519359 | 0.389270 | | 1.22 | 0.5 | 0.1 | no | 6850 | 1.05 | 80 | -7.291661 | 0.305238 | | 1.22 | 0.75 | 0 | no | 6850 | 1.05 | 80 | -99.921825 | 4.676361 | | 1.22 | 0.75 | 0.03 | no | 6850 | 1.05 | 80 | -37.786402 | 1.043892 | | 1.22 | 0.75 | 0.06 | no | 6850 | 1.05 | 80 | -24.349539 | 0.540590 | | 1.22 | 0.75 | 0.1 | no | 6850 | 1.05 | 80 | -16.991652 | 0.476656 | | 1.22 | 1 | 0 | no | 6850 | 1.05 | 80 | -153.906780 | 5.771269 | | 1.22 | 1 | 0.03 | no | 6850 | 1.05 | 80 | -62.282640 | 1.650028 | | 1.22 | 1 | 0.06 | no | 6850 | 1.05 | 80 | -41.269896 | 1.023946 | | 1.22 | 1 | 0.1 | no | 6850 | 1.05 | 80 | -30.459276 | 0.709085 | | 1.5 | 0.5 | 0 | no | 6850 | 1.05 | 80 | -22.567109 | 1.256201 | | 1.5 | 0.5 | 0.03 | no | 6850 | 1.05 | 80 | -12.827874 | 0.406269 | | 1.5 | 0.5 | 0.06 | no | 6850 | 1.05 | 80 | -8.984458 | 0.353071 | | 1.5 | 0.5 | 0.1 | no | 6850 | 1.05 | 80 | -6.122860 | 0.273504 | | 1.5 | 0.75 | 0 | no | 6850 | 1.05 | 80 | -46.331743 | 3.043897 | | 1.5 | 0.75 | 0.03 | no | 6850 | 1.05 | 80 | -25.480960 | 0.623478 | | 1.5 | 0.75 | 0.06 | no | 6850 | 1.05 | 80 | -20.544395 | 0.513046 | | 1.5 | 0.75 | 0.1 | no | 6850 | 1.05 | 80 | -15.963979 | 0.423004 | | 1.5 | 1 | 0 | no | 6850 | 1.05 | 80 | -80.113517 | 4.517405 | | 1.5 | 1 | 0.03 | no | 6850 | 1.05 | 80 | -46.584805 | 1.147201 | | 1.5 | 1 | 0.06 | no | 6850 | 1.05 | 80 | -38.612784 | 0.960015 | | 1.5 | 1 | 0.1 | no | 6850 | 1.05 | 80 | -32.637345 | 0.731384 | | 1.75 | 0.5 | 0 | no | 6850 | 1.05 | 80 | -14.607892 | 0.528480 | | 1.75 | 0.5 | 0.03 | no | 6850 | 1.05 | 80 | -10.254863 | 0.365188 | | 1.75 | 0.5 | 0.06 | no | 6850 | 1.05 | 80 | -7.498926 | 0.304159 | | 1.75 | 0.5 | 0.1 | no | 6850 | 1.05 | 80 | -5.649028 | 0.255103 | | 1.75 | 0.75 | 0 | no | 6850 | 1.05 | 80 | -32.131914 | 2.131819 | | 1.75 | 0.75 | 0.03 | no | 6850 | 1.05 | 80 | -22.482546 | 0.581924 | | 1.75 | 0.75 | 0.06 | no | 6850 | 1.05 | 80 | -18.872879 | 0.490967 | | 1.75 | 0.75 | 0.1 | no | 6850 | 1.05 | 80 | -16.257046 | 0.442219 | | 1.75 | 1 | 0 | no | 6850 | 1.05 | 80 | -58.419274 | 2.578410 | | 1.75 | 1 | 0.03 | no | 6850 | 1.05 | 80 | -44.958183 | 1.051717 | | 1.75 | 1 | 0.06 | no | 6850 | 1.05 | 80 | -39.468709 | 0.807320 | | 1.75 | 1 | 0.1 | no | 6850 | 1.05 | 80 | -35.685962 | 0.737811 | | 2 | 0.5 | 0 | no | 6850 | 1.05 | 80 | -11.742031 | 0.427606 | | 2 | 0.5 | 0.03 | no | 6850 | 1.05 | 80 | -8.663732 | 0.318802 | | 2 | 0.5 | 0.06 | no | 6850 | 1.05 | 80 | -6.911089 | 0.284117 | | 2 | 0.5 | 0.1 | no | 6850 | 1.05 | 80 | -5.328520 | 0.236393 | | 2 | 0.75 | 0 | no | 6850 | 1.05 | 80 | -25.142769 | 0.631636 | | 2 | 0.75 | 0.03 | no | 6850 | 1.05 | 80 | -21.505863 | 0.541126 | | 2 | 0.75 | 0.06 | no | 6850 | 1.05 | 80 | -19.081321 | 0.496165 | | 2 | 0.75 | 0.1 | no | 6850 | 1.05 | 80 | -17.335526 | 0.465488 | | 2 | 1 | 0 | no | 6850 | 1.05 | 80 | -55.270666 | 2.703693 | | 2 | 1 | 0.03 | no | 6850 | 1.05 | 80 | -45.999289 | 1.088333 | | 2 | 1 | 0.06 | no | 6850 | 1.05 | 80 | -43.026259 | 0.999600 | | 2 | 1 | 0.1 | no | 6850 | 1.05 | 80 | -39.797122 | 0.860774 | ### Zero-silent-step filter | T | wA | wR | g=0 required | stale / BPS | attract | n | mean_diff | se | |---:|---:|---:|:---:|---:|---:|---:|---:|---:| | 1.22 | 0.5 | 0.1 | yes | 6850 | 1.05 | 80 | -4.202344 | 0.253129 | | 1.22 | 0.75 | 0.1 | yes | 6850 | 1.05 | 80 | -9.223847 | 0.342452 | | 1.5 | 0.5 | 0.1 | yes | 6850 | 1.05 | 80 | -3.468755 | 0.229218 | | 1.5 | 0.75 | 0.1 | yes | 6850 | 1.05 | 80 | -9.095921 | 0.315299 | | 2 | 0.5 | 0.1 | yes | 6850 | 1.05 | 80 | -3.164504 | 0.208804 | | 2 | 0.75 | 0.1 | yes | 6850 | 1.05 | 80 | -10.045553 | 0.300206 | ### Coarse stale-fee retuning | T | wA | wR | g=0 required | stale / BPS | attract | n | mean_diff | se | |---:|---:|---:|:---:|---:|---:|---:|---:|---:| | 1.22 | 0.5 | 0.1 | no | 3000 | 0.75 | 80 | -43.564758 | 0.944883 | | 1.22 | 0.5 | 0.1 | no | 3000 | 1.05 | 80 | -40.326519 | 0.839382 | | 1.22 | 0.5 | 0.1 | no | 3000 | 1.35 | 80 | -39.217489 | 0.804442 | | 1.22 | 0.5 | 0.1 | no | 4500 | 0.75 | 80 | -18.204629 | 0.422889 | | 1.22 | 0.5 | 0.1 | no | 4500 | 1.05 | 80 | -15.523185 | 0.375024 | | 1.22 | 0.5 | 0.1 | no | 4500 | 1.35 | 80 | -16.046448 | 0.366394 | | 1.22 | 0.5 | 0.1 | no | 5500 | 0.75 | 80 | -8.127584 | 0.247728 | | 1.22 | 0.5 | 0.1 | no | 5500 | 1.05 | 80 | -6.682703 | 0.216123 | | 1.22 | 0.5 | 0.1 | no | 5500 | 1.35 | 80 | -7.564269 | 0.216510 | | 1.22 | 0.5 | 0.1 | no | 6850 | 0.75 | 80 | -7.211887 | 0.299816 | | 1.22 | 0.5 | 0.1 | no | 6850 | 1.35 | 80 | -8.178831 | 0.310894 | | 1.22 | 0.5 | 0.1 | no | 8500 | 0.75 | 80 | -155.748082 | 7.100546 | | 1.22 | 0.5 | 0.1 | no | 8500 | 1.05 | 80 | -159.943060 | 6.962257 | | 1.22 | 0.5 | 0.1 | no | 8500 | 1.35 | 80 | -157.383310 | 7.011818 | | 2 | 0.5 | 0.1 | no | 3000 | 0.75 | 80 | -44.234351 | 0.962543 | | 2 | 0.5 | 0.1 | no | 3000 | 1.05 | 80 | -41.081115 | 0.864105 | | 2 | 0.5 | 0.1 | no | 3000 | 1.35 | 80 | -40.018084 | 0.820457 | | 2 | 0.5 | 0.1 | no | 4500 | 0.75 | 80 | -18.653148 | 0.445790 | | 2 | 0.5 | 0.1 | no | 4500 | 1.05 | 80 | -16.406927 | 0.390999 | | 2 | 0.5 | 0.1 | no | 4500 | 1.35 | 80 | -16.747601 | 0.372725 | | 2 | 0.5 | 0.1 | no | 5500 | 0.75 | 80 | -8.132172 | 0.236277 | | 2 | 0.5 | 0.1 | no | 5500 | 1.05 | 80 | -6.989916 | 0.200238 | | 2 | 0.5 | 0.1 | no | 5500 | 1.35 | 80 | -7.516970 | 0.192374 | | 2 | 0.5 | 0.1 | no | 6850 | 0.75 | 80 | -5.685574 | 0.260064 | | 2 | 0.5 | 0.1 | no | 6850 | 1.35 | 80 | -5.985934 | 0.238410 | | 2 | 0.5 | 0.1 | no | 8500 | 0.75 | 80 | -158.409379 | 7.991271 | | 2 | 0.5 | 0.1 | no | 8500 | 1.05 | 80 | -158.729902 | 7.971963 | | 2 | 0.5 | 0.1 | no | 8500 | 1.35 | 80 | -158.755156 | 7.991521 | ### Gap-filtered stale-fee refinement | T | wA | wR | g=0 required | stale / BPS | attract | n | mean_diff | se | |---:|---:|---:|:---:|---:|---:|---:|---:|---:| | 1.5 | 0.5 | 0.1 | yes | 5500 | 0.8 | 80 | -6.074898 | 0.214246 | | 1.5 | 0.5 | 0.1 | yes | 5500 | 1.05 | 80 | -5.256007 | 0.199919 | | 1.5 | 0.5 | 0.1 | yes | 5500 | 1.25 | 80 | -5.708750 | 0.199744 | | 1.5 | 0.5 | 0.1 | yes | 6000 | 0.8 | 80 | -3.355718 | 0.155085 | | 1.5 | 0.5 | 0.1 | yes | 6000 | 1.05 | 80 | -3.007849 | 0.150059 | | 1.5 | 0.5 | 0.1 | yes | 6000 | 1.25 | 80 | -3.521386 | 0.147301 | | 1.5 | 0.5 | 0.1 | yes | 6500 | 0.8 | 80 | -2.426207 | 0.172072 | | 1.5 | 0.5 | 0.1 | yes | 6500 | 1.05 | 80 | -2.463240 | 0.163021 | | 1.5 | 0.5 | 0.1 | yes | 6500 | 1.25 | 80 | -3.070238 | 0.163134 | | 1.5 | 0.5 | 0.1 | yes | 7000 | 0.8 | 80 | -4.073347 | 0.265914 | | 1.5 | 0.5 | 0.1 | yes | 7000 | 1.05 | 80 | -4.312470 | 0.256292 | | 1.5 | 0.5 | 0.1 | yes | 7000 | 1.25 | 80 | -5.076885 | 0.388976 | | 1.75 | 0.5 | 0.1 | yes | 5500 | 0.8 | 80 | -6.150676 | 0.216200 | | 1.75 | 0.5 | 0.1 | yes | 5500 | 1.05 | 80 | -5.350380 | 0.198997 | | 1.75 | 0.5 | 0.1 | yes | 5500 | 1.25 | 80 | -5.711068 | 0.194630 | | 1.75 | 0.5 | 0.1 | yes | 6000 | 0.8 | 80 | -3.399612 | 0.163203 | | 1.75 | 0.5 | 0.1 | yes | 6000 | 1.05 | 80 | -2.941059 | 0.151275 | | 1.75 | 0.5 | 0.1 | yes | 6000 | 1.25 | 80 | -3.354074 | 0.163082 | | 1.75 | 0.5 | 0.1 | yes | 6500 | 0.8 | 80 | -2.398338 | 0.162137 | | 1.75 | 0.5 | 0.1 | yes | 6500 | 1.05 | 80 | -2.292208 | 0.157477 | | 1.75 | 0.5 | 0.1 | yes | 6500 | 1.25 | 80 | -2.757613 | 0.162039 | | 1.75 | 0.5 | 0.1 | yes | 7000 | 0.8 | 80 | -3.902763 | 0.252875 | | 1.75 | 0.5 | 0.1 | yes | 7000 | 1.05 | 80 | -4.010772 | 0.229113 | | 1.75 | 0.5 | 0.1 | yes | 7000 | 1.25 | 80 | -4.435895 | 0.228117 | | 2 | 0.5 | 0.1 | yes | 5500 | 0.8 | 80 | -6.447966 | 0.222081 | | 2 | 0.5 | 0.1 | yes | 5500 | 1.05 | 80 | -5.595881 | 0.200633 | | 2 | 0.5 | 0.1 | yes | 5500 | 1.25 | 80 | -5.934949 | 0.194313 | | 2 | 0.5 | 0.1 | yes | 6000 | 0.8 | 80 | -3.689679 | 0.168474 | | 2 | 0.5 | 0.1 | yes | 6000 | 1.05 | 80 | -3.213578 | 0.156888 | | 2 | 0.5 | 0.1 | yes | 6000 | 1.25 | 80 | -3.535474 | 0.159172 | | 2 | 0.5 | 0.1 | yes | 6500 | 0.8 | 80 | -2.712562 | 0.171963 | | 2 | 0.5 | 0.1 | yes | 6500 | 1.05 | 80 | -2.555764 | 0.150191 | | 2 | 0.5 | 0.1 | yes | 6500 | 1.25 | 80 | -2.882859 | 0.155175 | | 2 | 0.5 | 0.1 | yes | 7000 | 0.8 | 80 | -3.845738 | 0.249391 | | 2 | 0.5 | 0.1 | yes | 7000 | 1.05 | 80 | -3.808324 | 0.223559 | | 2 | 0.5 | 0.1 | yes | 7000 | 1.25 | 80 | -4.234765 | 0.210773 | ## Full Strategy.sol SHA-256: `0b89253b497d3d6bebfb67d76464ac44c91d07629ede8aa492326118279198dc`. Hash the exact UTF-8 contents inside the following Solidity fence, including its final LF byte. This source compiles with the pinned simulator's standard AMMStrategyBase.sol and IAMMStrategy.sol. ```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 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 = 6500 * 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 = PHAT_ALPHA_RETAIL; if (firstInStep) { bool arbLike = ret <= wmul(sigmaHat, 1750000000000000000); arbLike = arbLike && trade.timestamp <= lastTs + 1; alpha = arbLike ? 500000000000000000 : 100000000000000000; } 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); } 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"; } } ```