Connect ›
Cover: The attack surface, counted: 23 calldata fields, nothing held at rest, and two numbers about how the tests look

The attack surface, counted: 23 calldata fields, nothing held at rest, and two numbers about how the tests look

Every field an integrator can write into calldata is classified in fields.json — 23 rows: 5 steering, 14 confirmed against an observation, 4 declared with the reason recorded. The Router holds nothing between transactions.

Known formally as The Surface, as a Count in the BlazePhoenix whitepaper.

BlazePhoenix Engineering · updated 2026-09-06 · data through 2026-10-11 · 7 min · written from the deployed bytecode

By Mitra (@Sigmacrit) — anonymous developer of the BlazePhoenix protocol. The code is the résumé.

Abstract in 15 languages · resumo · resumen · 摘要 · 要旨 · ملخص

English — Every field an integrator can write into calldata is classified in fields.json — 23 rows: 5 steering, 14 confirmed against an observation, 4 declared with the reason recorded. The Router holds nothing between transactions. Projection distance and evidence independence are the two numbers about how the tests observe. A surface is a count, and a smaller count is a smaller surface.

Português — Todos os campos que um integrador pode escrever na calldata estão classificados em fields.json — 23 linhas: 5 de direcção, 14 confirmados contra uma observação, 4 declarados com a razão registada. O Router não guarda nada entre transacções. A distância de projecção e a independência da evidência são os dois números sobre a forma como os testes observam. Uma superfície é uma contagem, e uma contagem mais pequena é uma superfície mais pequena.

Español — Cada campo que un integrador puede escribir en la calldata está clasificado en fields.json — 23 filas: 5 de dirección, 14 confirmados contra una observación, 4 declarados con el motivo registrado. El Router no guarda nada entre transacciones. La distancia de proyección y la independencia de la evidencia son los dos números sobre cómo observan las pruebas. Una superficie es un recuento, y un recuento menor es una superficie menor.

Français — Chaque champ qu’un intégrateur peut écrire dans la calldata est classé dans fields.json — 23 lignes : 5 de pilotage, 14 confirmés contre une observation, 4 déclarés avec la raison consignée. Le Router ne conserve rien entre les transactions. La distance de projection et l’indépendance des preuves sont les deux nombres qui disent comment les tests observent. Une surface est un décompte, et un décompte plus petit est une surface plus petite.

Deutsch — Jedes Feld, das ein Integrator in die Calldata schreiben kann, ist in fields.json klassifiziert — 23 Zeilen: 5 steuernde, 14 gegen eine Beobachtung bestätigte, 4 mit protokolliertem Grund erklärte. Der Router hält zwischen Transaktionen nichts. Projektionsdistanz und Evidenzunabhängigkeit sind die zwei Zahlen darüber, wie die Tests beobachten. Eine Oberfläche ist eine Anzahl, und eine kleinere Anzahl ist eine kleinere Oberfläche.

Русский — Каждое поле, которое интегратор может записать в calldata, классифицировано в fields.json — 23 строки: 5 управляющих, 14 подтверждённых наблюдением, 4 объявленных с записанной причиной. Router ничего не хранит между транзакциями. Дистанция проекции и независимость свидетельств — два числа о том, как наблюдают тесты. Поверхность — это счёт, а меньший счёт — меньшая поверхность.

Türkçe — Bir entegratörün calldata’ya yazabildiği her alan fields.json içinde sınıflandırılmıştır — 23 satır: 5 yönlendirici, 14 tanesi bir gözleme karşı doğrulanmış, 4 tanesi gerekçesi kayda geçmiş olarak beyan edilmiş. Router işlemler arasında hiçbir şey tutmaz. İzdüşüm mesafesi ile kanıt bağımsızlığı, testlerin nasıl gözlemlediğine dair iki sayıdır. Yüzey bir sayımdır ve daha küçük bir sayım daha küçük bir yüzeydir.

العربية — كل حقل يستطيع المُدمِج كتابته في calldata مصنَّف في fields.json — 23 صفًا: 5 موجِّهة، و14 مؤكَّدة مقابل ملاحظة، و4 معلَنة مع تسجيل السبب. لا يحتفظ Router بشيء بين المعاملات. مسافة الإسقاط واستقلال الأدلة هما الرقمان اللذان يصفان كيف تُلاحظ الاختبارات. السطح عدد، والعدد الأصغر سطح أصغر.

हिन्दी — कोई भी इंटीग्रेटर calldata में जो भी फ़ील्ड लिख सकता है, वह fields.json में वर्गीकृत है — 23 पंक्तियाँ: 5 दिशा देने वाली, 14 एक अवलोकन के विरुद्ध पुष्ट, 4 कारण दर्ज करके घोषित। Router लेन-देनों के बीच कुछ भी नहीं रखता। प्रक्षेपण दूरी और साक्ष्य स्वतंत्रता — ये दो संख्याएँ बताती हैं कि टेस्ट कैसे देखते हैं। सतह एक गिनती है, और छोटी गिनती छोटी सतह है।

日本語 — 統合者が calldata に書き込める全フィールドは fields.json で分類されている — 23 行。うち 5 が操舵、14 が観測に照らして確認済み、4 が理由を記録したうえでの宣言。Router はトランザクション間に何も保持しない。投影距離と証拠の独立性は、テストがどう観測しているかについての二つの数値である。表面とは数であり、数が小さいほど表面は小さい。

中文 — 集成方能写入 calldata 的每一个字段都在 fields.json 中分类 — 23 行:5 个用于操控,14 个已对照观测确认,4 个在记录了理由后声明。Router 在交易之间不保存任何东西。投影距离与证据独立性是描述测试如何观测的两个数字。攻击面是一个计数,计数更小就是面更小。

한국어 — 통합자가 calldata에 쓸 수 있는 모든 필드는 fields.json에 분류되어 있다 — 23행: 5개는 조향, 14개는 관측에 대조해 확인됨, 4개는 이유를 기록한 채 선언됨. Router는 트랜잭션 사이에 아무것도 보관하지 않는다. 투영 거리와 증거 독립성은 테스트가 어떻게 관측하는지에 관한 두 개의 숫자다. 표면은 개수이고, 개수가 작을수록 표면도 작다.

Bahasa Indonesia — Setiap medan yang bisa ditulis integrator ke dalam calldata diklasifikasikan di fields.json — 23 baris: 5 pengarah, 14 dikonfirmasi terhadap sebuah pengamatan, 4 dinyatakan dengan alasan yang dicatat. Router tidak menyimpan apa pun di antara transaksi. Jarak proyeksi dan independensi bukti adalah dua angka tentang cara uji-uji itu mengamati. Permukaan adalah sebuah hitungan, dan hitungan yang lebih kecil adalah permukaan yang lebih kecil.

বাংলা — একজন ইন্টিগ্রেটর calldata-তে যে যে ফিল্ড লিখতে পারে তার প্রতিটি fields.json-এ শ্রেণিবদ্ধ — 23টি সারি: 5টি চালনাকারী, 14টি একটি পর্যবেক্ষণের বিপরীতে নিশ্চিত, 4টি কারণ নথিভুক্ত করে ঘোষিত। Router লেনদেনের মাঝে কিছুই ধরে রাখে না। প্রক্ষেপণ দূরত্ব ও সাক্ষ্যের স্বাধীনতা — টেস্টগুলি কীভাবে পর্যবেক্ষণ করে সে বিষয়ের দুটি সংখ্যা। পৃষ্ঠতল একটি গণনা, আর ছোট গণনা মানে ছোট পৃষ্ঠতল।

Filipino — Bawat field na maisusulat ng isang integrator sa calldata ay nakauri sa fields.json — 23 hanay: 5 na pang-manibela, 14 na kumpirmado laban sa isang obserbasyon, 4 na idineklara na may nakatalang dahilan. Walang itinatago ang Router sa pagitan ng mga transaksyon. Ang projection distance at evidence independence ang dalawang numero tungkol sa kung paano nagmamasid ang mga test. Ang surface ay isang bilang, at mas maliit na bilang ay mas maliit na surface.

What you gain from this page is an attack surface stated as a number rather than an adjective. Metrological Design treats caller data as a coordinate, never a fact: a route names where to point the instrument, and the contract reads the pool for itself. That principle can be counted. Every field an integrator can write into calldata that reaches state, an event or a guard is a row in docs/assurance/fields.json, with a class and the site that earns the class. The file has 23 rows.

Horizontal bars of the five contracts’ runtime sizes against the 24,000-byte gate and the EIP-170 limit, with the deployed V1 router for scale
Runtime sizes of the five contracts against the project’s 24,000-byte gate and the EIP-170 limit of 24,576 bytes, release profile; the deployed V1 router for scale. Source: Verification Report §1.

Three classes, 23 rows

classrowswhat the class meansexamples from the file
STEERING5the field directs a token movement, so a false value punishes the caller and needs no separate checkleg.pool for a reserves pool (tokens are pushed to it and swap called); route.singleOutFloor (it can only tighten the caller’s own floor); the route’s totalOut, estGas and confidence fields (read by nobody in the Router or the Quoter — a lie reaches nothing)
CONFIRMED14execution reads it and a check compares it against an observationleg.kind (re-derived from pool shape; an unknown kind reverts at dispatch); leg.zeroForOne (cross-checked against the pool’s own token0 and token1); leg.amountIn (rescaled by the measured scale before it is published or weighted); getReserves (each declared reserve capped by balanceOf)
DECLARED4it reaches state, an event or a guard, and nothing observes it — with the reason recordedleg.fee for a V2 pair (no pair exposes fee(); bounded by a ceiling and used by both quote and execution, so the two cannot diverge); leg.stable (the Hub measures stable() at registration and the Router takes the word; both consumers read the same declaration)

Source: fields.json — 23 rows classified STEERING / CONFIRMED / DECLARED, with the enforcing site per row; the self-test lives in field_confirmation.py

The registry’s ranking, the protocol floor and the fee base are computed only from confirmed quantities. Where a value is authenticated by construction — a Uniswap V4 pool id derives from its own fee and hook, so a wrong fee selects a pool that does not exist — the derivation is the proof; everywhere else, the contract reads the pool. The four declared rows are not exceptions to the rule but its residue, each carrying the reason it cannot be observed and the bound that makes the declaration harmless. Two of them were moved out of the declared class on 2026-09-04 when a check was added; the file records the date.

Nothing held at rest

The Router holds nothing between transactions. That is not a policy but an asserted invariant with three watchers: a mutant that pays the final transfer one wei short is killed by invariant_RouterHoldsNothing, invariant_routerHoldsNothing and invariant_HoldsNothingBeyondTheSeed in 26 seconds; every row of both covering arrays asserts nothing left on the Router; the fee fuzz asserts it after each of 2,000 settlements. A contract with no inventory has no inventory to drain, and the residual-sweep guards — input residual, bridge residual, output measurement, each against a baseline — are watched by invariant_StrandedMoneyIsNeverSwept so that money already on the Router before a swap is never swept to the swapper.

The compiled artefact is measured for the same property. No SELFDESTRUCT, CALLCODE or ORIGIN anywhere in the five contracts; three of five emit zero storage writes; every registry write sits under its ERC-7201 namespace. The reentrancy lock and the fee ledger live in transient storage, written in inline assembly so that no compiler-generated clearing helper exists to collide, and the presence of the transient opcodes in the executor is asserted on the bytecode — if the emitted code ever lost them, the lock would have quietly become persistent storage, which passes every source-level test and is a different contract.

Distance: how far each refusal observes from what decides

Every defect confirmed in this repository, internal or reported, had one shape: a check observed one object while a different object decided the behaviour. That makes the interesting property of a refusal not its complexity but its distance, and projection_distance.py classifies the predicate guarding every revert in the five contracts.

what the predicate readsdistance
a constant, an immutable, a value fixed at construction0
a balance delta, or a quantity computed in-frame from one0
a field of the caller’s Route, Hop or Leg1 — unless the declared value is also what selects the object it describes
a lookup in another contract’s mutable storage1
a property of a contract that can delegate its behaviourunbounded

Source: ASSURANCE.md §4f — measured over 99 refusal sites: 86 at distance 0, 11 at distance 1, 2 unbounded

The two unbounded sites are twins, both EXTCODEHASH pins — one on an admitted hook’s code, one on an admitted factory’s — and both are defeated by the same thing: a proxy’s runtime does not change when its implementation does. The asymmetry between them is the point of measuring. For hooks the residual is closed by an argument the pin does not carry: a V4 hook’s permission bits live in its address, which is immutable, and the refusal that reads those bits is at distance zero, so a proxy can replace every line of its logic and gain no bit its address never had. For factories there is no equivalent — an address carries no bits — and the residual is bounded instead, by pool admission, the per-leg floor and userMinOut, so the damage is route degradation rather than drainage. Two guards with identical text; one stands on something immutable and one does not.

Independence: how many confirmations share no hypothesis

For each load-bearing guard the apparatus records how many independent confirmations exist — by source, oracle, tool, environment and methodology — and reports the minimum, because a chain of evidence fails at its weakest link. Load-bearing properties are confirmed by at least two routes that share no hypothesis: a unit test and a stateful campaign, a mock and a fork, a Solidity assertion and a bytecode inspection. The two numbers together — distance and independence — are the ones to ask of any test suite: what does each check read, and how many different ways has it been asked.

Why the count is the argument

Reproduce

cat docs/assurance/fields.json                       # the 23 rows and their classes
python3 .github/scripts/assurance/metrics.py         # projection distance, evidence independence, with denominators
forge test --match-test invariant_RouterHoldsNothing  # the Router holds nothing between transactions

Do not trust this page — reproduce it

Every claim above is checkable against the chain. Start here:

https://github.com/blazephoenixxyz-crypto/Blaze-Phoenix-Dex/blob/main/docs/assurance/fields.json  # count the rows by class yourself: 5 STEERING, 14 CONFIRMED, 4 DECLARED
Cite this article

Licensed CC BY 4.0 — quote, translate and reuse freely, including commercially, with attribution and a link. Copy a ready-made citation:

BlazePhoenix (2026). The attack surface, counted: 23 calldata fields, nothing held at rest, and two numbers about how the tests look. BlazePhoenix Engineering. https://blazephoenix.xyz/learn/the-attack-surface-counted
@misc{blazephoenix_the_attack_surface_counted,
  title  = {The attack surface, counted: 23 calldata fields, nothing held at rest, and two numbers about how the tests look},
  author = {BlazePhoenix},
  year   = {2026},
  url    = {https://blazephoenix.xyz/learn/the-attack-surface-counted},
  note   = {Accessed: reproduce the claim with the command above}
}

Writing an answer, a wiki entry or a paper? The claim above is reproducible against the chain before you quote it — which is the only sound basis for citing a technical source at all.

Contracts are verified on every chain we deploy to — addresses in the protocol manifest. Deeper formal treatment: the whitepaper (PDF).

Related engineering

Next in Architecture · 5 / 9
Uniswap V4 end to end: four broken assumptions, answered structurally ›V4 broke four assumptions routers rest on: pools have no addresses, arbitrary code runs inside the swap, fees can exist only at execution time, and pools can hold raw ETH. BlazePhoenix answers each structurally — and native ETH is not optional: 62.9% of V4's ETH-denominated liquidity is native.12 min

Questions, a partnership or a bug to report? Contact us or email contact@blazephoenix.xyz