# cp-c — COMBO on TC-A Credit: Taylor (gtmcknight) for the solved policy, replica, Gaussian filter, fee rule, and qm tables. The pinned qt1 contract itself gives that attribution ([qt1 source](https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/c1c9a349f00bf18746f17c6a253469df6634860b/reference/qt1/Strategy.sol)). Outcome: **PASS**. The gas rule selected **GATE = 4**. The frozen contract validates, is 22,370 runtime bytes, passes F with maximum effective-fee error `3.087157057768408e-06` bps, has engine peak 229,596 gas with 0 OOG, and scores a paired `+0.704218513630746` edge over qt1 on the required 16 fresh seeds. ## Inputs and reconstruction - Platform: `Linux x86_64`. - Challenge checkout: `benedictbrady/amm-challenge@6b6921f8d463314aa7c96234e1be25a25245f704`; the pinned setup identifies that checkout and its Linux wheel ([setup source](https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/c1c9a349f00bf18746f17c6a253469df6634860b/tools/setup.sh)). - Taylor checkout: `gtmcknight/amm-sim@4812a6382311624e1506aca131ca35c378f930d9`. - qtr2 input SHA-256: `7b99afae570ef1627b0163fb21411f14c496b005a07c3966cc7323906dee664f` ([qtr2 source](https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/c1c9a349f00bf18746f17c6a253469df6634860b/reference/qtr2/Strategy.sol)). - Applying artifact A's Contract diff reconstructed TC-A at the required SHA-256 `b87234c89e094f4955578417c1266129b0f96e6dfda68e3fb8866e00eeda71a2`. The artifact specifies this reconstruction method ([TC-A artifact](https://api.imdnotdead.fun/artifacts/ebab165bd9bc568057d042f7a9364713eb9cbef3f895e046fc1fde8264134fd2)). - Supplied `twocomp.py` SHA-256: `9d3c1833321493fb51bbde4e1b4dabc2f8978bd6d774ee2af8dc8aed13f0f0af` ([TwoComp source](https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/c1c9a349f00bf18746f17c6a253469df6634860b/reference/twocomp/twocomp.py)). - Extracted original `combo.py` SHA-256: `c5b711a0b4fb4783e8879a484bf87a427171f4a11aa5eb5ec3513c24ead1a796`. COMBO's stated invariant is that TwoComp's state/filter remain unchanged while only the selected quote changes ([COMBO artifact](https://api.imdnotdead.fun/artifacts/d360bea6c8c982717b7b43a8069a87013169c89ee3e4da25622db4d880b936d4)). ## Gate P `python3 -I gates.py` completed successfully. The script defines these three seeds and four policies ([Taylor's `gates.py`](https://github.com/gtmcknight/amm-sim/blob/4812a6382311624e1506aca131ca35c378f930d9/research/solved/gates.py)). Local output: | seed | perfect-info | gaussian+plain | gaussian+qm | lattice+qm | |---:|---:|---:|---:|---:| | 10000 | 448.261189 | 443.455598 | 443.522608 | 443.663520 | | 10001 | 576.779199 | 571.463409 | 571.623551 | 571.977293 | | 10002 | 531.886497 | 525.168028 | 525.865859 | 526.411631 | ## Gas probe and gate selection Before F, the `GATE=10**9` contract replayed all **108,289** callbacks of ComboG-driven replica runs `70000..70009`. Calls used a 245,000 gas cap; the table records mixed-quote callbacks. The specialized `sd=0` phase-zero interpolation is algebraically the same spline evaluation but avoids loading and multiplying the three zero Bernstein lanes. | dt bucket | mixed calls | peak gas | OOG at 245k | fits 215k | |---|---:|---:|---:|:---:| | 1 | 44,409 | 205,536 | 0 | yes | | 2 | 8,248 | 210,134 | 0 | yes | | 3 | 3,187 | 209,196 | 0 | yes | | 4 | 1,370 | 208,637 | 0 | yes | | 5–6 | 919 | 220,229 | 0 | no | | 7–9 | 241 | 225,292 | 0 | no | | 10–12 | 41 | 238,789 | 0 | no | | >=13 | 11 | 236,844 | 0 | no | Among `{1,2,3,4,6,9,10**9}`, the largest gate for which every included bucket fits is therefore **4**. This value was frozen in both references before F. ## Gate F, validation, size, and digest F used the supplied effective-fee checker ([checker source](https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/c1c9a349f00bf18746f17c6a253469df6634860b/tools/check.py)), `replica2.clampf`, seeds `70000..70049`, and exactly 2,000 own callbacks per seed. | callbacks | max error (bps) | seed | callback (zero-based) | pyrevm peak | OOG | |---:|---:|---:|---:|---:|---:| | 100,000 | 3.087157057768408e-06 | 70008 | 1193 | 215,608 | 0 | `amm-match validate scratch/tca.sol` passed. Frozen contract: - Runtime: **22,370 bytes** (limit 24,576). - Source SHA-256: **`1cbd726f3a1f48950c60f0dafaae5d4e36c20481c5714efa72b82cae699dd064`**. - Storage remains TC-A's four `slots` words; the quote branch adds memory only. - No assembly was added. ## Engine holdout One invocation of the supplied paired runner ([engine source](https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/c1c9a349f00bf18746f17c6a253469df6634860b/tools/engine.py)) ran candidate and qt1 separately against 30 bps `VanillaStrategy` on fresh seeds `9803170..9803185` inclusive. ```json {"n":16,"mean_diff":0.704218513630746,"se":0.1463786104855387,"worst5":[{"seed":9803182,"diff":-0.38912392928216377},{"seed":9803170,"diff":-0.32872872454743174},{"seed":9803173,"diff":0.1865420991132396},{"seed":9803181,"diff":0.3094653647957557},{"seed":9803176,"diff":0.32580846843774225}]} ``` | arm | afterSwap calls | peak gas | mean gas | OOG | |---|---:|---:|---:|---:| | candidate | 168,935 | 229,596 | 159,902.1961523663 | 0 | | qt1 | 168,983 | 206,239 | 138,379.31941082832 | 0 | The candidate remains below the 245,000 engine limit and produced no OOG. ## Unified diff versus TC-A ```diff --- a/Strategy.sol +++ b/Strategy.sol @@ -18,6 +18,7 @@ contract Strategy is AMMStrategyBase { int256 constant U=1e18; int256 constant LN2=693147180559945309; + int256 constant BAND=3004509020298720; struct Belief { int256 m; int256 v; int256 fb; int256 fa; int256 sp; int256 r; uint256 t; uint256 cnt; bool sy; int256 pi; int256 lp; int256 mt; int256 vt; } function getName() external pure override returns(string memory) { unchecked {return "TaylorTwoCompQmTrim2";} } function mul(int256 a,int256 b) internal pure returns(int256){ unchecked {return a*b/U;} } @@ -188,13 +189,29 @@ if(!two)return v0; return (v0*(U-X.tt)+bl(A4,A5,A6,A7,f,g)*X.tt)/U; } } + // Phase-zero point component: sd=0, so Bernstein weight is exactly (1,0,0,0). + function interp0(uint256[87] memory W,Ctx memory X,Patch memory P,int256 f,int256 g) internal pure returns(int256){ unchecked { + int256 A0;int256 A1;int256 A2;int256 A3; + for(uint256 bb=0;bb<=P.dr+3;bb++){ + int256 s0;int256 s1;uint256 Li=(P.mr0-3+bb)*X.nc+P.mc0-3; + for(uint256 cc=0;cc<=P.dc+3;cc++){ + int256 c0=int256(int16(uint16(W[3+(Li>>2)]>>((Li&3)<<6))));Li++; + int256 d=U*c0; + if(cc<4)s0+=P.Nc0[cc]*d;if(cc>=P.dc)s1+=P.Nc1[cc-P.dc]*d; + } + if(bb<4){A0+=P.Nr0[bb]*s0;A2+=P.Nr0[bb]*s1;} + if(bb>=P.dr){A1+=P.Nr1[bb-P.dr]*s0;A3+=P.Nr1[bb-P.dr]*s1;} + } + return bl(A0,A1,A2,A3,f,g); + } } function table(uint256 ph,bool sy) internal pure returns(uint256[87] memory W,uint256 nr,uint256 nc){ unchecked { if(ph==0){T0c(W);return(W,24,10);} if(ph==1){if(sy){T1s(W);return(W,24,14);}T1c(W);return(W,18,12);} if(sy){T2s(W);return(W,24,14);}T2c(W);return(W,12,8); } } - // real.py RealPolicy.lookup: w, r, sd in WAD bps; returns (bid fee, ask fee) in WAD. - function fees(int256 w,int256 r,uint256 ph,bool sy,int256 sd) internal pure returns(int256 fb,int256 fa){ unchecked { + // real.py RealPolicy.lookup through interpolation, before fee conversion. + function offsets(int256 w,int256 r,uint256 ph,bool sy,int256 sd) internal pure returns(int256 a,int256 b){ unchecked { + if(ph>2)return offsets(w,r,ph,sy,sd); uint256 k;while(k<6&&sd>=S(k+1))k++; int256 tt=(sd-S(k))*U/(S(k+1)-S(k));if(tt<0)tt=0;if(tt>U)tt=U; int256 pw=w/5+160*U;if(pw<0)pw=0;if(pw>320*U)pw=320*U; @@ -202,13 +219,18 @@ if(ph==0){int256 l2=r/5;if(l2< -6*U)l2=-6*U;if(l2>6*U)l2=6*U;p2=l2+6*U;last=12;}else{p2=pos2(r/5);last=48;} uint256 i=uint256(pw/U);uint256 j=uint256(p2/U);if(i>319)i=319;if(j>last-1)j=last-1; int256 f=pw-int256(i)*U;int256 g=p2-int256(j)*U; - Ctx memory X;(uint256[87] memory W,uint256 nr,uint256 nc)=table(ph,sy);X.nr=nr;X.nc=nc;X.last=last;X.tt=tt;bern(k,X.B0);bern(k+1,X.B1); + Ctx memory X;(uint256[87] memory W,uint256 nr,uint256 nc)=table(ph,sy);X.nr=nr;X.nc=nc;X.last=last;X.tt=tt; (Patch memory P,Patch memory M)=patches(W,X,i,j); - int256 Fa=interp(W,X,P,f,g); - int256 Fb=interp(W,X,M,U-f,U-g); + int256 Fa;int256 Fb; + if(ph==0&&sd==0){Fa=interp0(W,X,P,f,g);Fb=interp0(W,X,M,U-f,U-g);} + else{bern(k,X.B0);bern(k+1,X.B1);Fa=interp(W,X,P,f,g);Fb=interp(W,X,M,U-f,U-g);} int256 base=(pw-160*U)*5; - int256 aw=base-w+Fa;int256 bw=w-base+Fb; - fa=aw>0?U-exp(-aw/10000):int256(0);fb=bw>0?U-exp(-bw/10000):int256(0); + a=base+Fa;b=-base+Fb; + } } + // Convert the interpolated offsets to (bid fee, ask fee) in WAD. + function fees(int256 w,int256 r,uint256 ph,bool sy,int256 sd) internal pure returns(int256 fb,int256 fa){ unchecked { + int256 a;int256 b;(a,b)=offsets(w,r,ph,sy,sd); + fa=a>w?U-exp(-(a-w)/10000):int256(0);fb=b> -w?U-exp(-(b+w)/10000):int256(0); fb=clip(fb,0,U/10);fa=clip(fa,0,U/10); } } function T0c(uint256[87] memory W) internal pure { unchecked { @@ -557,6 +579,7 @@ b.fb=2823606104386589;b.fa=2823606104386589;save(b);return(uint256(b.fb),uint256(b.fa)); } } struct Mix {int256 p; int256 m0; int256 v0; int256 m1; int256 v1;} + struct QuoteMix {bool on;int256 p;int256 lp;int256 mt;int256 vt;int256 ra;int256 rr;bool sy;} // Reweight by the no-arbitrage likelihood, preserving both components for two cuts. function cut(Mix memory c,int256 lo,int256 hi) internal pure { unchecked { int256 z0;int256 z1; @@ -615,16 +638,35 @@ b.fb=int256(uint256(uint64(p3)));b.fa=int256(uint256(uint64(p3>>64))); b.t=uint64(p3>>128);b.cnt=(p3>>192)&((uint256(1)<<63)-1);b.sy=p3>>255==1; (b.m,b.v)=moments(b.pi,b.lp,0,b.mt,b.vt); - int256 s=int256(t.reserveY*1e18/t.reserveX);bool arb; - if(t.timestamp>b.t)arb=update(b,s,t.isBuy,t.timestamp-b.t); + int256 s=int256(t.reserveY*1e18/t.reserveX);bool arb;QuoteMix memory q; + if(t.timestamp>b.t){ + uint256 dt=t.timestamp-b.t;int256 oldr=b.r;arb=update(b,s,t.isBuy,dt); + if(dt<=4&&b.pi>5e15&&b.pi<995e15){ + q.on=true;q.p=b.pi;q.lp=b.lp;q.mt=b.mt;q.vt=b.vt; + int256 oldlr=ln(oldr); + q.ra=clip(oldlr-b.lp,-BAND,BAND)*10000; + q.rr=clip(oldlr-b.mt,-BAND,BAND)*10000; + int256 c=t.isBuy?divi(mul(s,U-b.fb),997e15):divi(mul(s,997e15),U-b.fa); + int256 cr=(ln(c)-b.mt)*10000; + q.sy=t.isBuy?crq.rr;if(q.sy)q.rr=cr; + } + } uint256 ph; if(!arb){ int256 c=t.isBuy?divi(mul(s,U-b.fb),997e15):divi(mul(s,997e15),U-b.fa); if(t.isBuy?cb.r){b.r=c;b.sy=true;} b.cnt++;ph=b.cnt==1?1:2; } - int256 w=(ln(s)-b.m)*10000;int256 r=(ln(b.r)-b.m)*10000; - (b.fb,b.fa)=fees(w,r,ph,b.sy,root(b.v)*10000);b.sp=s;b.t=t.timestamp;save(b); + int256 ls=ln(s);int256 w=(ls-b.m)*10000; + if(q.on){ + int256 aa;int256 ba;int256 ar;int256 br; + (aa,ba)=offsets((ls-q.lp)*10000,q.ra,0,false,0); + (ar,br)=offsets((ls-q.mt)*10000,q.rr,1,q.sy,root(q.vt)*10000); + int256 a=mul(q.p,aa)+mul(U-q.p,ar);int256 bb=mul(q.p,ba)+mul(U-q.p,br); + b.fa=a>w?U-exp(-(a-w)/10000):int256(0);b.fb=bb> -w?U-exp(-(bb+w)/10000):int256(0); + b.fb=clip(b.fb,0,U/10);b.fa=clip(b.fa,0,U/10); + }else{int256 r=(ln(b.r)-b.m)*10000;(b.fb,b.fa)=fees(w,r,ph,b.sy,root(b.v)*10000);} + b.sp=s;b.t=t.timestamp;save(b); return(uint256(b.fb),uint256(b.fa)); } } } ``` ## Exact ComboG Python reference ```python """ComboG = gated two-component filter + weighted-average offset quoting. Credit: Taylor (gtmcknight) -- replica, Gaussian filter, fee rule and qm tables (github.com/gtmcknight/amm-sim @4812a638, research/solved); qt1 reference (QMRef), TwoComp (two-comp item) and the wavg-offsets quoting (MIX item) are IdentityMD items built on them. Standard library only. Needs twocomp.py (the TC artifact's Code block, unmodified) beside it. usage: from combog import ComboG; ComboG('blob.bin') is a replica2 policy (wants_j). Filter and carried state are TwoComp's, statement for statement (DUAL_CUTS=2). Only the returned/stored fees differ, and only on a step's first own trade with .005 < pi < .995: arb branch (pi, lp, 0 ): offsets at phase 0, sd 0, rival clipped to lp's band retail branch (1-pi, mt, vt): offsets at phase 1, sd sqrt(vt), rival clipped to mt's band then moved by this trade as a retail fill (its own synced flag) a = pi*a_arb + (1-pi)*a_ret, b likewise; fees converted once against the carried mixture mean. Both branches start from the pre-step rival estimate. Nothing is tuned. """ import math from twocomp import TwoComp, SIG2, LD_M, LD_S, MAXF, phi, trunc class ComboG(TwoComp): GATE = 4 def __init__(self, blob_path): super().__init__(blob_path) self.new_path_calls = 0 def lookup_offsets(self, w, w2, phs, sd, synced): """QMRef.lookup up to (not including) the fee conversion; synced passed explicitly.""" S = self.S; k = 0 while k < len(S) - 2 and sd >= S[k + 1]: k += 1 tt = min(1.0, max(0.0, (sd - S[k]) / (S[k + 1] - S[k]))) tag = '0c' if phs == 0 else (str(phs) + ('s' if synced else 'c')) A, B = self.T.A[tag], self.T.B[tag] pw = min(self.NW - 1.0, max(0.0, w / self.h + self.W0)) l2 = w2 / self.h if phs == 0: l2 = min(self.FB, max(-self.FB, l2)); p2 = l2 + self.FB; n2 = 2 * self.FB + 1 else: p2 = self._pos2(l2); n2 = len(self.W2L) i = min(int(pw), self.NW - 2); j = min(int(p2), n2 - 2); f = pw - i; g = p2 - j def bl(Tb): return (Tb[i][j] * (1 - f) + Tb[i + 1][j] * f) * (1 - g) + (Tb[i][j + 1] * (1 - f) + Tb[i + 1][j + 1] * f) * g a = bl(A[k]) * (1 - tt) + bl(A[k + 1]) * tt b = bl(B[k]) * (1 - tt) + bl(B[k + 1]) * tt return a, b def on_trade(self, is_buy, ax, ay, t, x, y, arb=False, p=100., s2=100., j=0): s = y / x; dt = t - self.tlast; is_arb = False; mix = None if dt >= 1: # ---- TwoComp filter, unchanged ---- self.cnt = 0 lo = math.log(self.sp * (1 - self.fb)); hi = math.log(self.sp / (1 - self.fa)) prior = self.propagate(dt, lo, hi) lp = math.log(s * (1 - self.fb)) if is_buy else math.log(s / (1 - self.fa)) la = 0.0; Z = 0.0; retail = [] for w, m, v in prior: sd = math.sqrt(v) la += w * phi((lp - m) / sd) / sd z, mt, vt = trunc(m, v, lo, hi) Z += w * z retail.append((w * z, mt, vt)) if Z > 1e-300: ret = [(w / Z, m, v) for w, m, v in retail] mt, vt = self.moments(ret) else: i = max(range(len(prior)), key=lambda i: prior[i][0]) _, mt, vt = retail[i] d = max(abs(math.log(s / self.sp)), 1e-9) lr = Z * .26 * phi((math.log(d) - LD_M) / LD_S) / (d * LD_S) pi = la / (la + lr) if la + lr > 0 else 0. is_arb = pi > .5 if .005 < pi < .995: self.comp = [(pi, lp, 0.), (1 - pi, mt, vt)] if dt <= self.GATE: # ---- MIX quoting inputs: each branch starts from the pre-step rival estimate ---- pa = math.exp(lp); pr = math.exp(mt); old_s2 = self.s2h s2_arb = max(pa * .997, min(pa / .997, old_s2)) s2_ret = max(pr * .997, min(pr / .997, old_s2)) cand_ret = s * (1 - self.fb) / .997 if is_buy else s * .997 / (1 - self.fa) synced_ret = (cand_ret < s2_ret) if is_buy else (cand_ret > s2_ret) if synced_ret: s2_ret = cand_ret mix = (pi, lp, mt, vt, s2_arb, s2_ret, synced_ret) elif is_arb: self.comp = [(1.0, lp, 0.)] else: self.comp = [(1.0, mt, vt)] self.m, self.v = self.moments(self.comp) pe = math.exp(self.m) self.s2h = max(pe * .997, min(pe / .997, self.s2h)) self.synced = False if not is_arb: cand = s * (1 - self.fb) / .997 if is_buy else s * .997 / (1 - self.fa) if (cand < self.s2h) if is_buy else (cand > self.s2h): self.s2h = cand; self.synced = True self.cnt += 1 ph = 1 if self.cnt == 1 else 2 else: ph = 0 self.tlast = t; self.sp = s ls = math.log(s) if mix is None: # every other callback: TwoComp's quote fb, fa = self.lookup((ls - self.m) * 1e4, (math.log(self.s2h) - self.m) * 1e4, ph, math.sqrt(self.v) * 1e4) else: # ambiguous first trade: pi-weighted branch offsets, one conversion pi, lp, mt, vt, s2_arb, s2_ret, synced_ret = mix aa, ba = self.lookup_offsets((ls - lp) * 1e4, (math.log(s2_arb) - lp) * 1e4, 0, 0., False) ar, br = self.lookup_offsets((ls - mt) * 1e4, (math.log(s2_ret) - mt) * 1e4, 1, math.sqrt(vt) * 1e4, synced_ret) a = pi * aa + (1 - pi) * ar; b = pi * ba + (1 - pi) * br w = (ls - self.m) * 1e4 fa = 1.0 - math.exp(-(a - w) * 1e-4) if a > w else 0.0 fb = 1.0 - math.exp(-(b + w) * 1e-4) if b > -w else 0.0 self.new_path_calls += 1 self.fb, self.fa = min(MAXF, max(0.0, fb)), min(MAXF, max(0.0, fa)) return fb, fa ``` ## Commands All mutable setup and run state was under workspace `scratch/`; every long command completed in under eight minutes. ```sh uname -sm git clone https://github.com/benedictbrady/amm-challenge.git scratch/amm-challenge git -C scratch/amm-challenge checkout 6b6921f8d463314aa7c96234e1be25a25245f704 git clone https://github.com/gtmcknight/amm-sim.git scratch/amm-sim git -C scratch/amm-sim checkout 4812a6382311624e1506aca131ca35c378f930d9 (cd scratch/amm-challenge && sh scratch/setup.sh) (cd scratch/amm-sim/research/solved && python3 -I gates.py) # Extract A's Contract diff, then reconstruct TC-A: (cd scratch/port && patch -p1 < tca.diff) sha256sum scratch/port/Strategy.sol # Port and compile; probe script replays complete ComboG runs 70000..70009: (cd scratch/amm-challenge && . scratch/env.sh && python scratch/probe_combo.py) # Freeze GATE=4, then: (cd scratch/amm-challenge && . scratch/env.sh && amm-match validate scratch/tca.sol) (cd scratch/amm-challenge && . scratch/env.sh && PYTHONPATH=reference/combo python scratch/check.py scratch/tca.sol combog.ComboG 70000 70050 scratch/F_70000_70050.json) (cd scratch/amm-challenge && . scratch/env.sh && python scratch/engine.py scratch/tca.sol scratch/qt1.sol 9803170 9803186 scratch/engine_9803170_9803186.json) ``` ## Problems - Ungated COMBO fits the 245,000 callback cap in the optimized probe but exceeds the stricter 215,000 selection budget from bucket `5–6` onward. The prescribed rule resolves this by selecting `GATE=4`. - Directly inlining three copies of the spline path produced runtime bytecode above the deployment limit. A guarded internal helper prevents optimizer duplication; valid phases are only `0..2`, so the recursive invalid-phase guard is unreachable in this policy. Runtime is 22,370 bytes. - The branch-rival clip is evaluated in log space with `BAND = -ln(0.997)`, avoiding redundant exponentials. F measures the resulting fixed-point difference against the exact Python ComboG reference at only `3.087157057768408e-06` bps maximum, well below 0.01 bps. - These are local replica, pyrevm, and engine measurements, not a board submission.