เวอร์ชัน 1.2.0 ให้ราคาเท่าเดิมทุกหลัก แต่ยิง RPC น้อยลง 92 % บน HyperEVM — จาก 26 request ต่อ quote เหลือ 2 — เพราะไม่ถาม pool ที่ไม่มีอยู่จริงอีกต่อไป ทดสอบแบบ A/B กับเวอร์ชัน 1.1.0 บน npm ที่ block เดียวกัน 18 กรณี ราคาต่างกัน 0.00 bps ทุกกรณี
Report #1 found that most of the SDK's RPC calls went to pools that were never deployed. Round 1 fixes exactly that problem (a pool registry plus a runtime negative cache), folds the extra decimals() request into the multicall, caches immutable state, retunes batch sizes and disables routes that never have a live pool. Every change was A/B-tested against the published 1.1.0 with the same workload at the same block. Prices are byte-identical on all 18 cases.
BNB's official endpoint is fastest with small batches (report #1 §4), so the BNB batch size was set to 300 as a compromise: fewer requests than 1.1.0 and 13–37 % faster. HyperEVM uses 250-call batches: two requests per quote; the public node rejects batches of ~1,300.
| pair | calls 1.1.0 | calls 1.2.0 | wasted 1.1.0 | wasted 1.2.0 | bytes 1.1.0 | bytes 1.2.0 |
|---|
Both versions quoted 1 / 100 / 1,000 units of three pairs per chain, twice, back-to-back at a pinned block. Δ = (1.2.0 − 1.1.0) / 1.1.0 in basis points; the gate fails a round at −5 bps.
| chain | cases | worst Δ price | same route chosen | verdict |
|---|---|---|---|---|
| HyperEVM | HYPE→USDT0, USDT0→WHYPE, kHYPE→USDT0 × 1 / 100 / 1,000 | 0.00 bps | 9 / 9 | pass |
| BNB Chain | BNB→USDT, BUSD→USDT, ETH→CAKE × 1 / 100 / 1,000 | 0.00 bps | 9 / 9 | pass |
eth_call and silently serves the latest block (BNB's honors it). So on that endpoint two quotes 16 s apart can differ by 1–2 bps purely from market movement. The harness now detects this, keeps A and B back-to-back, and warns. For price-exact claims use a provider that honors block tags (Alchemy, QuickNode, own node).| # | change | effect | risk |
|---|---|---|---|
| R1 | Pool registry. A small table per chain (5.7 KB HyperEVM, 39 KB BNB) of which pools actually exist for each DEX route, generated by scanning the chain once. Pools known to be missing are never asked. Pairs outside the table are asked once and remembered for an hour if empty. | HyperEVM calls −65 %, wasted → 0 | table is a snapshot; a brand-new pool is invisible until regenerated (round 2 moves it to a shared KV store) |
| R2 | Batch sizes per chain from measurements, plus a cap on parallel requests and a “premium” preset for paid nodes. | 26 → 2 requests on HyperEVM | +15 % latency on HyperEVM's public node (two big batches vs 25 tiny ones) |
| R3 | Token decimals ride inside the multicall instead of their own request. | −1 request per quote | none |
| R4 | Cache for immutable state (token decimals, factory fee, Curve A) with TTL. | −172 calls per warm BNB quote | first quote per session still pays |
| R5 | Disabled 8 routes that never had a live pool for any tested pair (5 HyperEVM fee tiers, 3 BNB long-tail DEXes). | −231 calls per HyperEVM quote | needs a periodic route-health check |
| R8 | Retry, back-off and batch splitting when a node rejects a request. | no more whole-quote failures | retries add latency under sustained rate limiting |
| R10 | Interface fix: reserve checks optional for multi-asset models; unused dependencies removed. | correctness; smaller installs | none |
# A = npm @moromoro/moro-sdk@1.1.0, B = this branch's build; prices gated at 5 bps
npx ts-node -T -O '{"module":"commonjs"}' benchmark/ab-test.ts --chain hyperevm --a baseline --b dist --runs 2 --pause 15000
npx ts-node -T -O '{"module":"commonjs"}' benchmark/ab-test.ts --chain bsc --a baseline --b dist --runs 2
# regenerate a pool registry after adding routes or tokens
npx ts-node -T -O '{"module":"commonjs"}' benchmark/build-pool-registry.ts --chain hyperevm
Round write-up with every row: benchmark/rounds/1.md; raw samples: benchmark/results/2026-09-13-*-round1-v1.2.0.json; protocol: benchmark/AB-TESTING.md — all on korrio/moro-sdk-optimized. The npm package stays at 1.1.0 until the team publishes.