
{"id":189965,"date":"2026-06-30T14:22:04","date_gmt":"2026-06-30T14:22:04","guid":{"rendered":"https:\/\/mycryptomania.com\/?p=189965"},"modified":"2026-06-30T14:22:04","modified_gmt":"2026-06-30T14:22:04","slug":"when-the-quote-becomes-calldata-the-fork-tests-whether-it-holds","status":"publish","type":"post","link":"https:\/\/mycryptomania.com\/?p=189965","title":{"rendered":"When the Quote Becomes Calldata. The Fork Tests Whether It Holds."},"content":{"rendered":"<p><em>A note on turning a Uniswap quote into API-native calldata, then replaying that transaction against pinned mainnet\u00a0state.<\/em><\/p>\n<p><a href=\"https:\/\/medium.com\/@egpivo\/9b610ae3493d\">Part I <\/a>stopped at the quote layer: route legs, output amounts, API-reported priceImpact, and blockNumber. It recorded what the router proposed. At larger sizes, that proposal became a spread of pools and intermediate hops, not a single\u00a0price.<\/p>\n<p>A desk sizing an exit acts on that quote; so does a risk pipeline that reads priceImpactas a risk number. On a centralized venue, a mistake there usually stays inside an operator\u2019s scope: an order cancelled, a fill refunded, a replacement issued. Once the quote becomes calldata, there is no venue operator between the user and pool execution, and the failure boundary moves from router proposal to encoded constraints. The quote alone cannot tell whether the next problem is invalid transaction construction, wallet authorization, gas estimation, state drift, ordering, or the final\u00a0fill.<\/p>\n<p>Part I sliced the quote layer; this post slices one execution layer: build the transaction from the quote, replay it against pinned mainnet state, and check whether the proposal survives, and where the route\u2019s complexity ends up. A valid quote does not mean valid calldata; a successful same-state replay does not mean a mined\u00a0receipt.<\/p>\n<h3>Readable quote, executable calldata<\/h3>\n<p>A \/quote response can show expected output, minimumAmount, route structure, and blockNumber, but none of those fields execute by themselves. The trade becomes executable only when \/swap returns a TransactionRequest: to, data, value, gasLimit, and encoded router instructions.<\/p>\n<p>The chain enforces only what the transaction encodes-most importantly the minimum output condition. Expected output and priceImpact are display fields, not the bytes the Universal Router will\u00a0run.<\/p>\n<p><strong>Fig. 1.<\/strong> Quote evidence vs transaction evidence. The quote records what the router proposed; `\/swap` materializes calldata; fork replay tests that calldata against pinned state. Ordering, MEV, fee payment, and inclusion sit outside this\u00a0article.<\/p>\n<p>The replay is a same-state execution check for the \/swap artifact, not a live fill. Fork setup and measured fields are in the run section\u00a0below.<\/p>\n<p>Uniswap\u2019s Trading API exposes this directly by separating from\u00a0:<\/p>\n<p>POST \/quote<br \/>  \u2192 POST \/swap with the returned quote<br \/>  \u2192 save TransactionRequest<br \/>  \u2192 fork at quote.blockNumber<br \/>  \u2192 seed wallet balance and approvals<br \/>  \u2192 send API-native calldata<br \/>  \u2192 measure output-token delta, minimumAmount, and gas<\/p>\n<p>Shell references: <a href=\"https:\/\/gist.github.com\/egpivo\/72f6c99f39bfc1b27238283e438db632#file-quote_to_swap-sh\">quote_to_swap.sh<\/a>and <a href=\"https:\/\/gist.github.com\/egpivo\/0e1ee51092d60ee0587ede159bde569a#file-replay_swap-sh\">replay_swap.sh<\/a>.<\/p>\n<h3>The fork replay\u00a0run<\/h3>\n<p><strong>Run ID:<\/strong> 20260619Tpart2v1<\/p>\n<p>I collected nine cells: USDC \u2192 WETH, AAVE, and MKR at $100, $10k, and $1M. Routing was Uniswap classic ( CLASSIC); protocols V2\/V3\/V4 via BEST_PRICE; UniswapX excluded.<\/p>\n<p>For each cell I POSTed \/quote, then POSTed \/swap with the returned quote object and archived both responses. \/swap used allowance-based calldata from the Trading API-not SDK reconstruction from route JSON. API simulateTransaction succeeded on all nine\u00a0cells.<\/p>\n<p>Each cell was replayed on a fresh Anvil mainnet fork at that cell\u2019s quote.blockNumber (blocks 25,350,126-25,350,128), with archive RPC state. I seeded a fixed test wallet with ETH for gas, USDC via anvil_setStorageAt, and USDC \u2192 Permit2 \u2192 Universal Router approvals. Replay sent exact API-native \/swap calldata to the router at 0x66a989&#8230;8Af.<\/p>\n<p>A signed-permit collection ( 20260619Tpart2v0) failed fork replay when permit sigDeadline preceded the pinned quote-block timestamp. That comparison run is archived; the primary evidence is the allowance path\u00a0above.<\/p>\n<p>Measured per row: fork_status, fork_output_amount, fork_vs_quote_bps, fork_meets_minimum, fork_gas_used, and api_simulation_status.<\/p>\n<h3>What the grid\u00a0shows<\/h3>\n<p>All nine cells replayed at pinned state, cleared minimumAmount, and matched the quote at 0 bps: the expected baseline for same block, same pool state, same calldata.<\/p>\n<p><strong>Fig. 2.<\/strong> Fork replay panel: WETH \/ AAVE \/ MKR \u00d7 $100 \/ $10k \/ $1M. Each cell reports fork status, fork vs quote (bps), `minimumAmount` pass\/fail, and gas used. Run `20260619Tpart2v1`; same-state replay matched the quote at 0\u00a0bps.<\/p>\n<p><strong>WETH $100<\/strong> routed through a single V3 hop. Fork gas was 140,975-the simple\u00a0control.<\/p>\n<p><strong>MKR $1M<\/strong> showed quote-layer output deterioration in Part I. Its seven-hop transaction still replayed at 0 bps and cleared the\u00a0minimum.<\/p>\n<h3>AAVE $1M: fragmented route, same-state pass<\/h3>\n<p>Part I flagged AAVE for route fragmentation and summary-field ambiguity. At $1M the quote carried <strong>13 pool legs across five parallel paths<\/strong> (V2\/V3\/V4 mix). \/swap returned 14,366 bytes of calldata. Fork gas was 2,386,700-roughly 17\u00d7 the WETH $100\u00a0control.<\/p>\n<p><strong>Fig. 3.<\/strong> USDC \u2192 AAVE at $1M: five parallel paths, 13 pool legs, V2\/V3\/V4 mix. Side panel: quote block 25,350,127, quoted output, `minimumAmount`, fork status. The route looked fragmented at quote time; it did not become a deterministic same-state failure.<\/p>\n<h3>Pilot panel: what route stress\u00a0becomes<\/h3>\n<p>The nine-cell replay is a controlled check, but it is too small to say much about route stress more generally. I therefore ran a pilot panel over 28 snapshot labels, 10 assets, and five input sizes: 1,400 intended cells. This was a pipeline pilot, not a historical backtest.<\/p>\n<p>The pilot produced 977 successful \/quote + \/swap rows. The strongest pattern was payload size: hop count versus calldata bytes had a Pearson correlation of 0.935; path count versus calldata bytes was\u00a00.917.<\/p>\n<p><strong>Fig. 4.<\/strong> Pilot panel: 1,400 intended cells; 977 successful `\/quote` + `\/swap` rows plotted. Hop count versus calldata bytes (Pearson <em>r<\/em> = 0.935). Marker size is USDC input size; descriptive, not\u00a0causal.<\/p>\n<p>From that panel I selected 118 stress rows for fork replay. Ninety replayed successfully at pinned state. The remaining 28-all high-complexity SHIB rows-stopped at eth_estimateGas.<\/p>\n<p>Three of those I direct-sent on fresh pinned forks with a 12M gas cap; all three executed at roughly 7M gas and cleared minimumAmount. The timeout was an estimator artifact, not an EVM failure-but that check covers only 3 rows. The remaining 25 still need the same follow-up.<\/p>\n<h3>What a fork replay result actually\u00a0means<\/h3>\n<p>The first all-green table raised a scope question: was this evidence, or only a same-state sanity check? Treating replay as one test stopped working once the non-receipts came from different layers.<\/p>\n<p><strong>Fig. 5.<\/strong> Where the evidence stopped across 118 selected stress-row replays. CRV stopped at configuration, COMP\/LDO at quote availability, the signed-permit path at wallet authorization, SHIB at gas estimation before direct-send replay, and AAVE at same-state EVM fork execution. A single pass\/fail column would erase those distinctions.<\/p>\n<p>A non-receipt is not one failure class. Configuration, authorization, estimation, and EVM execution fail at different boundaries.<\/p>\n<h3>Closing<\/h3>\n<p>Part I stopped at the quote. Here, same-state replay held, route complexity showed up in calldata size, and three SHIB estimator timeouts became roughly 7M-gas executions on bounded\u00a0forks.<\/p>\n<p>The harder part is keeping the labels straight: estimator timeout, authorization failure, configuration error, and EVM execution are different boundaries, even when all of them produce no mined\u00a0receipt.<\/p>\n<p>The next falsifiable check is narrow: direct-send the remaining 25 SHIB rows with bounded gas on pinned forks. Inclusion, ordering, MEV, state drift, and realized fill still need receipt-level evidence.<\/p>\n<h3>Appendix: sources<\/h3>\n<p><strong>Reproduce: <\/strong>quote_to_swap.sh (collect `\/quote` + `\/swap`) and <a href=\"https:\/\/gist.github.com\/egpivo\/0e1ee51092d60ee0587ede159bde569a\">replay_swap.sh<\/a> (fork\u00a0replay).<strong>Part I ladder:<\/strong> <a href=\"https:\/\/medium.com\/@egpivo\/9b610ae3493d\">The Price Moves First. DEX Routes Fray Before the Exit.<\/a>\u200a\u2014\u200aquote-layer route fraying; collection 20260618T134419Z.<strong>RWA exchange-risk context:<\/strong> <a href=\"https:\/\/medium.com\/thecapital\/where-rwa-exchange-risk-actually-sits-c9ad9fbb27a2\">Where RWA Exchange Risk Actually Sits<\/a>. Centralized venues can cancel, refund, or issue replacement objects; a DEX route has no default operator at execution time.<strong>Part II collection:<\/strong> Uniswap Trading API \/quote+ \/swap; fork replay via Anvil at `quote.blockNumber`.<strong>Pilot panel:<\/strong> 1,400 intended cells, 977 feature rows, and 118 selected fork\u00a0replays.<strong>API references:<\/strong> <a href=\"https:\/\/developers.uniswap.org\/docs\/api-reference\/aggregator_quote\">POST \/quote<\/a>, <a href=\"https:\/\/developers.uniswap.org\/docs\/api-reference\/create_swap_transaction\">POST \/swap<\/a>, <a href=\"https:\/\/developers.uniswap.org\/docs\/trading\/swapping-api\/integration-guide\">swapping integration guide<\/a>.<strong>Pre-execution tooling:<\/strong> <a href=\"https:\/\/support.metamask.io\/configure\/wallet\/security-alerts\/\">MetaMask security alerts<\/a> (transaction simulation before signing); <a href=\"https:\/\/docs.tenderly.co\/simulations\/single-simulations\">Tenderly single simulations<\/a> and <a href=\"https:\/\/docs.tenderly.co\/virtual-environments\/overview)%20(fork%20simulation\">virtual environments<\/a>().<\/p>\n<p>This post was originally published on my personal blog: <a href=\"https:\/\/egpivo.github.io\/2026\/06\/30\/when-the-quote-becomes-a-transaction.html\">https:\/\/egpivo.github.io\/2026\/06\/30\/when-the-quote-becomes-a-transaction.html<\/a><\/p>\n<p><a href=\"https:\/\/medium.com\/coinmonks\/when-the-quote-becomes-calldata-the-fork-tests-whether-it-holds-abeae0075dec\">When the Quote Becomes Calldata. The Fork Tests Whether It Holds.<\/a> was originally published in <a href=\"https:\/\/medium.com\/coinmonks\">Coinmonks<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>A note on turning a Uniswap quote into API-native calldata, then replaying that transaction against pinned mainnet\u00a0state. Part I stopped at the quote layer: route legs, output amounts, API-reported priceImpact, and blockNumber. It recorded what the router proposed. At larger sizes, that proposal became a spread of pools and intermediate hops, not a single\u00a0price. A [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":189966,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-189965","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-interesting"],"_links":{"self":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/189965"}],"collection":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=189965"}],"version-history":[{"count":0,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/189965\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/media\/189966"}],"wp:attachment":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=189965"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=189965"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=189965"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}