{"item":"ff-1","status":"done","summary":"The six afterSwap inputs and the policy's own fees carry one exact signal: the input amount sits on the reserve's float grid for an arb and not for retail. The sharpest form, an exact round trip through the Wad, flags every arb (0 missed of 245,404 on a Rust-order emulation) and false-flags 0.12% of retail first trades, against 0.30% plus 0.85% missed arbs for the KNOWN tolerance tell on Wads. Paired on tuning seeds 66000..66063 it adds +0.048 se 0.018 over the KNOWN tell on the Wad emulation and +0.024 se 0.015 on the replica, leaving 0.010 to 0.013 (within noise) to the true flag. A cheap fix, an absolute tol of 1e-18, gets +0.033 se 0.022 of that on the Wad emulation. Split/whole, rival reserves and the code-path replay are exact or near exact but redundant. A retail sell holds no exact information about p.","findings":[{"name":"1_exact_round_trip_arb_test","test":"Arb or retail on a first trade. The arb's input is a reserve difference divided by gamma, so it is exactly fl(n*g/gamma) for an integer n. Retail input is a random float. The test passes if some integer n near v/g gives fl(fl(n*g)/gamma) == amount bit for bit, where amount = amount_x if is_buy else amount_y, gamma = 1 - fee in force (fb if is_buy else fa), v = amount*gamma, z = reserve_x if is_buy else reserve_y, and g = min(ulp(z), ulp(z-v)). On the Wad engine the contract sees w = Wad::from_f64(amount), so the test becomes Wad::from_f64(fl(n*g/gamma)) == w. Python: g=min(ulp(z),ulp(z-v)); n0=round(v/g); any(W((n*g)/gam)==w for n in range(n0-2,n0+3)) with W(c)=int(c*1e18). Code: analyze.py exact_rt/wad_rt.","n":451551,"hit_rate":1.0,"false_rate":0.001066,"holds_in_rust_source":true,"reason":"Replica arithmetic, first trades on seeds 66000..66063: 245221/245221 arbs flagged, 220/206330 retail first trades false-flagged (KNOWN tolerance tell: 673 false, 0.00326). Rust-order emulation with Wad callbacks and Wad fees, same seeds: 245404/245404 arbs flagged and 244/206298 (0.001183) retail false-flagged. On the same Wad-emulated callbacks the KNOWN tolerance tell flags 243314/245404 arbs and false-flags 616 (0.002986). The 2,090 arbs it misses are all is_buy arbs with amount_x below about 6e-4 X: Wad truncation is coarser than the float ulp there, so v sits off the grid by more than tol = 2.2e-16*v. Why it holds in Rust: arbitrageur.rs computes amount_x = (x_virtual - rx)/gamma, and quote_sell_x returns total_y = (k/new_rx - reserve_y)/gamma. Both are a reserve difference (Sterbenz-exact, so on the reserve's float grid) divided by gamma, the same structure as replica2.py. Rust and replica2 differ in what follows: Rust keeps the fee in a bucket and updates reserves incrementally, while the replica sets y = K/x. That affects only the reserves the test reads for the grid exponent. False flags grow with order size: about ulp(amount)*gamma/g, i.e. roughly amount/reserve. Only the input amount discriminates: the output amount and both reserves land on reserve grids for arbs and retail alike, because x_out = rx - k/new_ry is itself a reserve difference.","value":{"note":"Paired over the KNOWN tell on tuning seeds 66000..66063 (64 seeds, replica RNG). This is the Gaussian+qm policy, soft=1, with r = min(1, 5*ulp(amount)*gamma/g) on a hit, else 0. These are diagnostics, not holdout scores. The whole remaining gap to the true flag is about 0.04 to 0.06, so no arb test can buy more than that.","replica_exact_minus_tol":{"n":64,"mean_diff":0.02414,"se":0.0149,"sum":1.5451,"sumsq":0.93235,"worst5":[-0.2282,-0.1503,-0.1316,-0.1307,-0.1091]},"replica_flag_minus_exact":{"n":64,"mean_diff":0.01301,"se":0.01589,"sum":0.83275,"sumsq":1.02864,"worst5":[-0.2071,-0.205,-0.2041,-0.2027,-0.2018]},"rust_emulation_exact_minus_tol":{"n":64,"mean_diff":0.0481,"se":0.01756,"sum":3.07842,"sumsq":1.39152,"worst5":[-0.2446,-0.2255,-0.184,-0.142,-0.1416]},"rust_emulation_flag_minus_exact":{"n":64,"mean_diff":0.01014,"se":0.01594,"sum":0.64887,"sumsq":1.03054,"worst5":[-0.2357,-0.2178,-0.2091,-0.2089,-0.2081]},"misread_first_trades":{"replica_tol":308,"replica_exact":144,"rust_tol":2335,"rust_exact":125,"of_first":451551},"tell_vs_no_tell_replica":{"n":64,"mean_diff":2.9447,"se":0.1386},"gas":"Not measured. A bit-exact port means emulating one IEEE division (n*g/gamma) and one multiply by 1e18, rounded to nearest, in 256-bit integers: a few hundred integer ops. Unported."}},{"name":"1b_wad_aware_tolerance_tell","test":"The KNOWN tolerance tell with one extra absolute term: tol = 2.220446e-16*v + 1e-18, on the floats WF(wad). It covers the Wad truncation of tiny amounts. Python: tellpol.tell_r(..., abs_tol=1e-18).","n":451702,"hit_rate":null,"false_rate":null,"holds_in_rust_source":true,"reason":"It is the cheap, Solidity-friendly half of finding 1, an integer distance-to-grid check like the KNOWN tell. On the Rust-order emulation, first-trade misreads fall from 2335 (KNOWN tell) to 290 (this) and 125 (exact round trip) of 451702. Per-test hit and false counts were not tabulated for this variant; only the policy misread counts were.","value":{"rust_emulation_tolw_minus_tol":{"n":64,"mean_diff":0.03295,"se":0.02182,"sum":2.10891,"sumsq":1.98916,"worst5":[-0.4295,-0.3519,-0.2789,-0.2453,-0.2314]},"replica_tolw_minus_tol":{"n":64,"mean_diff":0.00567,"se":0.01085,"sum":0.36279,"sumsq":0.47689,"worst5":[-0.2988,-0.1327,-0.1239,-0.0985,-0.0807]},"rust_emulation_exact_minus_tolw":{"n":64,"mean_diff":0.01515,"se":0.01554,"sum":0.96951,"sumsq":0.98884,"worst5":[-0.4719,-0.2594,-0.2177,-0.1846,-0.1821]}}},{"name":"2_split_or_whole","test":"Was a retail order split with the rival, or did it come to us whole? It is whole iff our post-trade marginal quote is still at least as good as the rival's pre-trade quote. Trader buys X (is_buy false): whole iff s/(1-fa) <= s2/0.997. Trader sells X (is_buy true): whole iff s*(1-fb) >= s2*0.997, with s = reserve_y/reserve_x after the trade. With the policy's own rival estimate s2h, the policy calls it a split when its candidate rival spot (s*(1-fb)/0.997 or s*0.997/(1-fa)) moves s2h, which is real.py's synced update.","n":458536,"hit_rate":0.968703,"false_rate":0.005421,"holds_in_rust_source":true,"reason":"All retail fills, replica, seeds 66000..66063: 410394 of 458536 were split (0.895). Given the TRUE rival pre-trade spot, the inequality decides split vs whole for 458332/458536 (0.99956). The rest are rival shares under router.rs MIN_AMOUNT 0.0001, which are dropped. Given only the policy's estimate (hit_rate/false_rate fields): it detects 397550/410394 splits and calls 261 of 48142 whole fills split. Rust emulation: 458456/458669 agree with the true state, and the estimate gets 397701 hits and 270 false. No bit-level marker exists. The split amount u1 = (r*(y2+g2*size)-y1)/d is an ordinary float. So the split/whole bit is exactly a function of the rival state, which the policy already tracks.","value":"Nothing new: real.py's synced flag already uses it. Its ceiling is the rival-tracking cost, 0.19 in the README's perfect-price setting."},{"name":"3_rival_reserves_after_split","test":"After a split, both pools sit at the same marginal price, so the rival's spot is s2 = s*(1-fb)/0.997 (trader sold X) or s*0.997/(1-fa) (trader bought X). With x2*y2 = K this gives x2 = sqrt(K/s2) and y2 = sqrt(K*s2). Python: analyze.py block (3).","n":410394,"hit_rate":1.0,"false_rate":0.0,"holds_in_rust_source":true,"reason":"Hit means the implied rival spot is within 1e-6 bps of the truth. Max error over 410394 replica split fills: 1.33e-11 bps; Rust emulation 410481 fills, max 1.22e-11 bps. Product: in replica2.py every update sets y = K/x, and |x2*y2/K-1| <= 2.2e-16. cfmm.rs does NOT keep it bit-exact: it recomputes k = reserve_x*reserve_y on each trade and moves the reserves incrementally (reserve_x += amount_x - fee_amount; reserve_y -= y_out, with y_out = ry - k/new_rx; fees go to a separate bucket). In the emulation k drifts by at most 1.78e-14 relative over 10,000 steps (end-of-run max 1.60e-14), so it is constant to about 1e-14. Consequence: after each split we know the rival's full reserves to about 1e-14 relative. After two consecutive splits in one step, the rival's pre-order reserves are known, so the whole order size (u1+u2) can be recovered. That size carries no information on p: see finding 4.","value":"At most the rival-tracking cost (README: 0.19 with the true price), and the s2 update in real.py already realises most of it. Rival reserves (rather than spot) add no decision-relevant state, because with constant K the spot determines the reserves."},{"name":"4_fair_price_on_retail_sell","test":"Look for exact information about p in a retail sell. router.rs converts the order to X as total_x = order.size / fair_price, with size a LogNormal draw (retail.rs). Take whole sells (no rival share), compare ln(amount_x*p) with ln(size), and run the grid tests on sell-side retail amounts.","n":24278,"hit_rate":null,"false_rate":null,"holds_in_rust_source":true,"reason":"Over 24278 whole retail sells, |ln(amount_x*p) - ln(size)| <= 0.036: the X amount is size/p up to the dropped <1e-4 rival share. But size is an independent lognormal with log-sd 1.2, so one sell tells ln p with sd 1.2. That is Fisher information (9.45e-4/1.2)^2 = 6e-7 of one step's prior. No bit structure: grid false-flag counts on retail first trades are 115 on sells vs 105 on buys (exact test, replica), the same rate. A split sell adds an equal-marginal-price equation that contains no p. The rival's share and the order size are recoverable (finding 3), but size_X = size_Y/p with size_Y unknown.","value":0.0},{"name":"5_rust_code_path_replay","test":"Own idea. In cfmm.rs an arb that buys X runs execute_sell_x (X amount in; total_y = net_y/gamma; reserve_y += total_y - (total_y - net_y)). A retail buy of X runs execute_buy_x_with_y (Y amount in; reserve_y += amount_y - amount_y*fee; x_out = rx - k/new_ry). A contract knows its previous reserves exactly as Wads, its own Wad fees and this callback's Wads, so it can replay both code paths over every float preimage of each Wad and see which reproduces all three Wads. Python: analyze.py rust_replay.","n":225677,"hit_rate":1.0,"false_rate":0.001095,"holds_in_rust_source":true,"reason":"Sell-side (is_buy false) first trades, Rust emulation: the arb path reproduces 122518/122518 arbs and 113/103159 retail fills. The retail path reproduces every retail fill and also 94532 arbs, so 27986 arbs (0.228) are certified arbs because the retail path fails. The 113 retail fills that pass the arb path are the same count the exact round trip false-flags on that side (113): the replay sees the same grid coincidence and nothing more. Buy side (is_buy true): arb and retail both run execute_buy_x, so the paths match for all of them and the replay carries no information. In replica2.py's arithmetic (y = K/x for both) the counts are 29224 certified arbs and 105 false.","value":"About 0 over finding 1. It cannot remove a false flag, because every retail fill passes the retail path. At most it multiplies a false flag's likelihood by 0.77."}],"best_arb_test":{"name":"exact Wad round trip (finding 1), Rust-order emulation, first trades, seeds 66000..66063","false_flag_rate_by_size_quartile":[{"y_range":[0.000156,2.861],"n":51574,"false":10,"false_rate":0.000194,"known_tol_false":24,"known_tol_false_rate":0.000465},{"y_range":[2.860551,5.773],"n":51574,"false":25,"false_rate":0.000485,"known_tol_false":77,"known_tol_false_rate":0.001493},{"y_range":[5.772623,12.031],"n":51574,"false":35,"false_rate":0.000679,"known_tol_false":96,"known_tol_false_rate":0.001861},{"y_range":[12.032082,874.291],"n":51576,"false":174,"false_rate":0.003374,"known_tol_false":419,"known_tol_false_rate":0.008124}],"missed":0,"arbs":245404,"retail_first":206298,"replica_arithmetic":{"false_flag_rate_by_size_quartile":[{"y_range":[0.000121,2.861],"n":51582,"false":13,"false_rate":0.000252,"known_tol_false":29,"known_tol_false_rate":0.000562},{"y_range":[2.861299,5.771],"n":51582,"false":17,"false_rate":0.00033,"known_tol_false":61,"known_tol_false_rate":0.001183},{"y_range":[5.770719,12.025],"n":51582,"false":47,"false_rate":0.000911,"known_tol_false":126,"known_tol_false_rate":0.002443},{"y_range":[12.02468,874.291],"n":51584,"false":143,"false_rate":0.002772,"known_tol_false":457,"known_tol_false_rate":0.008859}],"missed":0,"arbs":245221,"retail_first":206330},"size_quartiles_note":"Quartiles of the amount_y of retail first trades (Y units). false = exact test, known_tol_false = the KNOWN tolerance tell on the same trades."},"limitations":["Everything ran on replica RNG streams (seeds 66000..66063, 64 runs), never on the amm_sim_rs engine. 'Rust emulation' is sim.py mode 'rust': my Python transcription of cfmm.rs, arbitrageur.rs and router.rs (fee-bucket reserves, k = x*y recomputed, Wad::from_f64 truncation of callbacks, the policy's fees truncated to Wad and read back with to_f64). Python floats and Rust f64, including sqrt, are both IEEE correctly rounded, so the arithmetic should match bit for bit, but this was not checked against the engine.","engine.rs was not read. The step order (arbs, then retail), which pool is amm1 in the router, and the GBM price step come from replica2.py. The split itself is computed from pre-trade reserves, so execution order does not change any test.","No holdout seed (10000..12047) was used and no policy was scored on it. The paired numbers are tuning-seed diagnostics with se about 0.015 to 0.022, and differences under 0.03 are not resolved.","The r weight for an exact hit (5*ulp(amount)*gamma/g) is a rough prior, not fitted.","The gas cost of a bit-exact Wad round trip in Solidity is not measured. Finding 1b is the cheap integer form.","The grid argument relies on x_virtual - rx and k/new_rx - reserve_y being Sterbenz-exact (the two terms within a factor of 2), which holds for every arb on these runs but is not guaranteed for a 99%-capped arb."],"code_zb64":"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","code_sha256":"2a1556d9beb7fdbe5d3dd01a1a22fc9ed0927298fda1f5e02f65f42b60bd4b5d"}