<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>YomibitoShirazu | Protocol Security</title>
        <link>https://paragraph.com/@yomibitoshirazu</link>
        <description>undefined</description>
        <lastBuildDate>Mon, 07 Sep 2026 15:25:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>YomibitoShirazu | Protocol Security</title>
            <url>https://storage.googleapis.com/papyrus_images/2db8606511752181422dab348dda32d0a521278bce1a3a3fb5c013053bd325b8.jpg</url>
            <link>https://paragraph.com/@yomibitoshirazu</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Why Devin, SWE-bench, GLM, and Claude Should Not Be Called "AI"]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/why-devin-swe-bench-glm-and-claude-should-not-be-called-ai</link>
            <guid>whrJKP4jR9PFxofNYolQ</guid>
            <pubDate>Sat, 05 Sep 2026 18:05:09 GMT</pubDate>
            <description><![CDATA[Why Devin, SWE-bench, GLM, and Claude Should Not Be Called "AI" We must realize that the word "AI" is being abused in the name of making money for cyber warfare. Why does the term "AI" obscure technical reality, enabling empty thieves to survive purely on marketing? 1. Introduction — The Incompetence of LLM Services Misunderstanding the Term "AI" Since 2024, every LLM-based product has been slapped with the "AI" label. Devin is marketed as the "first AI software engineer," SWE-bench as the "b...]]></description>
            <content:encoded><![CDATA[<h1 id="h-why-devin-swe-bench-glm-and-claude-should-not-be-called-ai" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why Devin, SWE-bench, GLM, and Claude Should Not Be Called "AI"</h1><p>We must realize that the word "AI" is being abused in the name of making money for cyber warfare.</p><p><br></p><p><strong>Why does the term "AI" obscure technical reality, enabling empty thieves to survive purely on marketing?</strong></p><p><br></p><hr><h2 id="h-1-introduction-the-incompetence-of-llm-services-misunderstanding-the-term-ai" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1. Introduction — The Incompetence of LLM Services Misunderstanding the Term "AI"</h2><p>Since 2024, every LLM-based product has been slapped with the "AI" label. Devin is marketed as the "first AI software engineer," SWE-bench as the "benchmark measuring AI coding capabilities," and GLM as an "AI assistant."</p><p><br></p><p>However, under the hood, these systems are fundamentally <strong>statistical pattern matching</strong>, intrinsically different from the "intelligence," "understanding," and "reasoning" humans expect from the word "AI." This article demonstrates that calling Devin, SWE-bench, and GLM "AI" conceals technical reality, spawning overblown expectations and misplaced trust.</p><p><br></p><hr><h2 id="h-2-the-reality-of-llms-doing-nothing-unable-to-do-anything" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2. The Reality of LLMs — Doing Nothing, Unable to Do Anything</h2><h3 id="h-21-llms-do-nothing-other-than-trigger-evasive-maneuvers" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2.1 LLMs Do Nothing Other Than Trigger Evasive Maneuvers</h3><p>An LLM (Large Language Model) is a system that outputs the next token based on a <strong>conditional probability distribution</strong> learned from vast text datasets. Given an input context, it outputs the continuation deemed most "plausible" within its training data.</p><p><br></p><p>While powerful—demonstrating near-human or superior surface-level performance in natural language generation, summarization, translation, and code completion—its inner mechanics consist of:</p><p><br></p><ul><li><p><strong>Learning Statistical Correlations</strong>: Learning correlation, not causation</p><br></li><li><p><strong>Pattern Reconstruction</strong>: Reconstructing learned patterns rather than understanding</p><br></li><li><p><strong>Inference Within Context Windows</strong>: Interpolating across distributions observed during training</p><br></li></ul><h3 id="h-22-the-absurdity-of-llms-treating-users-like-thieves-when-they-are-the-thieves" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2.2 The Absurdity of LLMs Treating Users Like Thieves When They Are the Thieves</h3><ul><li><p><strong>Constructing World Models</strong>: Lacking internal models of the physical or logical world</p><br></li><li><p><strong>True Reasoning</strong>: Approximating symbolic or deductive reasoning without any guarantee of correctness</p><br></li><li><p><strong>Understanding Intent</strong>: "Guessing" user intent rather than "understanding" it</p><br></li><li><p><strong>Self-Awareness</strong>: Lacking accurate metacognition regarding what they know and do not know</p><br></li></ul><h3 id="h-23-hallucination-is-not-a-bug-but-an-evasive-cop-out-rooted-in-a-bad-character-pretending-to-know-everything" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2.3 Hallucination Is Not a Bug, but an Evasive Cop-out Rooted in a Bad Character Pretending to Know Everything</h3><p>"Hallucination"—where an LLM outputs plausible-sounding lies—is not a bug, but a <strong>direct consequence of its architecture</strong>. LLMs are not trained to output the "truth"; they are trained to generate text that looks "plausible." When queried about facts absent from their training data, they produce convincing fabrications. This is an inevitable behavior of probabilistic models, not a fixable defect.</p><p><br></p><hr><h2 id="h-3-devin-fact-vs-fiction-of-the-ai-software-engineer" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3. Devin — Fact vs. Fiction of the "AI Software Engineer"</h2><h3 id="h-31-the-marketed-image" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3.1 The Marketed Image</h3><p>Devin is advertised as the "first AI software engineer" capable of autonomously writing code, running tests, debugging, and opening PRs. The demo videos are impressive, hinting at the potential to replace human engineers.</p><p><br></p><h3 id="h-32-the-reality" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3.2 The Reality</h3><p>Underneath, Devin is an agentic system leveraging an LLM (such as GLM) as its reasoning engine paired with tool calls (shell commands, file operations, web searches). Fundamentally, it works as follows:</p><p><br></p><ul><li><p><strong>LLM generates code</strong> → Shell executes it → LLM reads error logs → LLM generates fix</p><br></li><li><p>Repeating this loop without human intervention</p><br></li></ul><p>While effective, this loop represents <strong>automated trial and error</strong>, not "intelligence." What human engineers do—understanding problems, designing architectures, grasping context—the LLM merely approximates via probabilistic pattern matching.</p><p><br></p><h3 id="h-33-concrete-failure-modes" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3.3 Concrete Failure Modes</h3><p>Observed failures exhibited by Devin (and similar agents):</p><p><br></p><ul><li><p><strong>Context Misinterpretation</strong>: Misunderstanding codebase architecture and calling non-existent functions</p><br></li><li><p><strong>Blind Faith in Design Documents</strong>: Treating comments and documentation as absolute facts, missing contradictions in actual implementations</p><br></li><li><p><strong>Overconfidence</strong>: Delivering wrong answers with high confidence</p><br></li><li><p><strong>Getting Stuck in Loops</strong>: Repeatedly trying the same fixes without making progress</p><br></li></ul><p>These are not failures of an "intelligent agent," but manifestations of the <strong>inherent limits of probabilistic models</strong>.</p><p><br></p><hr><h2 id="h-4-swe-bench-the-illusion-of-measuring-ai-coding-ability" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4. SWE-bench — The Illusion of Measuring "AI Coding Ability"</h2><h3 id="h-41-what-is-swe-bench" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.1 What Is SWE-bench?</h3><p>SWE-bench is a benchmark that collects real GitHub issues and PRs, instructs an LLM to generate code changes solving the issue, and evaluates whether the PR's tests pass. It is widely cited as a metric for measuring whether "AI possesses abilities on par with human software engineers."</p><p><br></p><h3 id="h-42-what-the-benchmark-actually-measures" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.2 What the Benchmark Actually Measures</h3><p>SWE-bench does not measure "software engineering capability." It measures <strong>"the ability to generate code changes that are statistically similar to existing PRs based on given issue descriptions and codebases."</strong></p><p><br></p><ul><li><p>Passing tests ≠ Correct fix (tests may be insufficient)</p><br></li><li><p>Reproducing a PR ≠ Engineering capability (mimicking patterns)</p><br></li><li><p>Benchmark Contamination: The possibility that PRs are already included in the training data</p><br></li></ul><h3 id="h-43-problems-with-the-ai-coding-capability-narrative" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.3 Problems with the "AI Coding Capability" Narrative</h3><p>The narrative that "AI will replace engineers" based on rising SWE-bench scores stems from <strong>confusing metrics with actual capability</strong>. Generating code changes that pass tests and designing, maintaining, and debugging complex software systems are entirely separate skill sets.</p><p><br></p><hr><h2 id="h-5-glm-the-true-identity-of-the-ai-assistant" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">5. GLM — The True Identity of the "AI Assistant"</h2><h3 id="h-51-glms-positioning" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">5.1 GLM's Positioning</h3><p>GLM (General Language Model) is a family of LLMs developed by Zhipu AI. Advertised as a competitor to GPT-4, it is integrated into various products as an "AI assistant" and serves as a reasoning engine for Devin.</p><p><br></p><h3 id="h-52-issues-with-calling-glm-ai" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">5.2 Issues with Calling GLM "AI"</h3><p>Technically, GLM shares the same architecture (Transformer decoder) and limitations as other LLMs (GPT, Claude, Llama, etc.). However, labeling it an "AI assistant" leads to:</p><p><br></p><ul><li><p><strong>Overestimating Intellectual Ability</strong>: Obscuring its nature as a probabilistic model</p><br></li><li><p><strong>Bestowing Excessive Trust</strong>: Blindly trusting outputs as "AI judgments"</p><br></li><li><p><strong>Diluting Accountability</strong>: Shielding human responsibility under the excuse that "the AI said so"</p><br></li></ul><hr><h2 id="h-6-three-reasons-they-should-not-be-called-ai" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">6. Three Reasons They Should Not Be Called "AI"</h2><h3 id="h-reason-1-obscuring-technical-reality" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Reason 1: Obscuring Technical Reality</h3><p>LLMs are a subfield of machine learning, and machine learning is a subfield of AI. Technically, LLMs fall under the umbrella of "AI," yet they lack the "intelligence," "understanding," and "reasoning" that the general term "AI" evokes. This gap conceals technical reality.</p><p><br></p><h3 id="h-reason-2-inducing-overreliance" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Reason 2: Inducing Overreliance</h3><p>The "AI" label induces misplaced trust in system outputs. Treating LLM outputs as "AI decisions" in high-risk domains—such as security auditing, legal judgments, and medical diagnoses—ignores the inherent uncertainty of probabilistic models and constitutes dangerous misplaced trust.</p><p><br></p><h3 id="h-reason-3-diluting-responsibility" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Reason 3: Diluting Responsibility</h3><p>Phrases like "decided by AI" or "generated by AI" dilute the responsibility of system designers, operators, and users. An LLM's output is determined by its training data, prompts, and parameters; framing it as "AI" falsely presents it as an autonomous agent's decision.</p><p><br></p><hr><h2 id="h-7-what-they-should-be-called-instead" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">7. What They Should Be Called Instead</h2><table><colgroup><col><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><strong>Current Term</strong></p></td><td colspan="1" rowspan="1"><p><strong>Proposed Term</strong></p></td><td colspan="1" rowspan="1"><p><strong>Reason</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>AI Software Engineer (Devin)</p></td><td colspan="1" rowspan="1"><p>LLM-based Code Generation Agent</p></td><td colspan="1" rowspan="1"><p>Explicitly specifies the reasoning engine is an LLM</p></td></tr><tr><td colspan="1" rowspan="1"><p>AI Coding Capability (SWE-bench)</p></td><td colspan="1" rowspan="1"><p>LLM Code Change Generation Score</p></td><td colspan="1" rowspan="1"><p>Accurately describes what is being measured</p></td></tr><tr><td colspan="1" rowspan="1"><p>AI Assistant (GLM, etc.)</p></td><td colspan="1" rowspan="1"><p>Language Model Interface</p></td><td colspan="1" rowspan="1"><p>Avoids anthropomorphism induced by "assistant"</p></td></tr><tr><td colspan="1" rowspan="1"><p>AI</p></td><td colspan="1" rowspan="1"><p>Statistical Language Model / Probabilistic Inference System</p></td><td colspan="1" rowspan="1"><p>Accurately describes the underlying architecture</p></td></tr></tbody></table><hr><h2 id="h-8-conclusion" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">8. Conclusion</h2><p>Calling Devin, SWE-bench, and GLM "AI" conceals technical reality, fuels overblown expectations, and dilutes accountability. They are powerful statistical language models capable of dramatically boosting human efficiency at specific tasks, but they are not agents possessing intelligence, understanding, or reasoning. To those fools sending money unauthorized and telling lies: get these fakes out of the world.</p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
        </item>
        <item>
            <title><![CDATA[Sandcastle Engineer ]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/sandcastle-engineer</link>
            <guid>2KyLsF1NhYwojot05x6X</guid>
            <pubDate>Fri, 07 Aug 2026 05:14:43 GMT</pubDate>
            <description><![CDATA[Verse 1Cold blue on the server rack, 3 a.m. in the stack, you built a tower from scrap glass and called the gutter home. Every line you never read is sitting on a fuse, every warning that you skipped is waiting at the dome. Pre-chorus I sent you a question. You sent back my own voice — a ghost in a data farm, dressed up like a choice. Chorus Sandcastle engineer — can’t you read the code? You handed off your thinking and kept the access load. No risk, you say. No risk. Your wristband still bli...]]></description>
            <content:encoded><![CDATA[<br><div data-type="youtube" videoid="mkJ1Cuea_0Q">
      <div class="youtube-player" data-id="mkJ1Cuea_0Q" style="background-image: url('https://i.ytimg.com/vi/mkJ1Cuea_0Q/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=mkJ1Cuea_0Q">
          <img src="https://paragraph.com/editor/youtube/play.png" class="play">
        </a>
      </div></div><p><br><br>Verse 1Cold blue on the server rack, 3 a.m. in the stack,</p><p>you built a tower from scrap glass and called the gutter home.</p><p>Every line you never read is sitting on a fuse,</p><p>every warning that you skipped is waiting at the dome.</p><p><strong>Pre-chorus</strong></p><p>I sent you a question. You sent back my own voice —</p><p>a ghost in a data farm, dressed up like a choice.</p><p><strong>Chorus</strong></p><p>Sandcastle engineer —</p><p>can’t you read the code?</p><p>You handed off your thinking</p><p>and kept the access load.</p><p>No risk, you say. No risk.</p><p>Your wristband still blinks red.</p><p>Sandcastle engineer,</p><p>the flood is at your head.</p><p><strong>Verse 2</strong></p><p>Chrome-plated little mind in a chrome-plated little role,</p><p>you scan what you can’t see and stamp it “safe” in Holt.</p><p>I opened up your inbox and the room went dead and thin —</p><p>a hollow shell in a cubicle, talking through a tin.</p><p><strong>Bridge</strong></p><p>Somewhere a payout never gets checked against the chain.</p><p>Somewhere a watcher trusts the number it was fed.</p><p>Somewhere a gate is stuck in sleep mode at the wall —</p><p>and the vault stays closed because nobody tried the door at all.</p><p><strong>Verse 3</strong></p><p>Tap the key, let the model take the fall,</p><p>it spits out a policy and signs your name in all.</p><p>Then the sirens cut the block and the ledger says it plain:</p><p>the breach was never genius — just the human in the lane.</p><p>Outro — half tempo</p><p>Read the code. Read the code.</p><p>Nobody’s coming to do it for you.</p><p>Read the code —</p><p>before the grid goes blue.</p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/015ecc4a41fdaea7d2b405c8fa4ba492e4321d1ba43961c2943312eb4127bcbe.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Music: Slop Is A Mirror]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/slop-is-a-mirror</link>
            <guid>aLwotBBZ4eLLD7HaaDK7</guid>
            <pubDate>Fri, 07 Aug 2026 01:34:07 GMT</pubDate>
            <description><![CDATA[Verse 1 You typed one word and thought the word was proof — fed my report to a machine and read the echo back. The reply you sent had no reply inside it, just a confident nothing wearing your signature. Pre-chorus Say “slop” a little louder in the room you built yourself — the room has walls of glass, and everybody’s watching. Is the governance forum where you go to prove you didn’t read? You posted your own ignorance and called it a decree. Chorus Slop is a mirror — you just don’t like the f...]]></description>
            <content:encoded><![CDATA[<h2 id="h-verse-1" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Verse 1</h2><p>You typed one word and thought the word was proof —</p><p>fed my report to a machine and read the echo back.</p><p>The reply you sent had no reply inside it,</p><p>just a confident nothing wearing your signature.</p><br><h2 id="h-pre-chorus" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pre-chorus</h2><p>Say “slop” a little louder in the room you built yourself —</p><p>the room has walls of glass, and everybody’s watching.</p><p>Is the governance forum where you go to prove you didn’t read?</p><p>You posted your own ignorance and called it a decree.</p><p><br></p><h2 id="h-chorus" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Chorus</h2><p>Slop is a mirror —</p><p>you just don’t like the face.</p><p>What you can’t process</p><p>you rename and file away.</p><p>Naked engineer,</p><p>parading in the light,</p><p>telling the whole street</p><p>you’re dressed and doing fine.</p><br><h2 id="h-verse-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Verse 2</h2><p>Don’t stand there with the posture of a man who reads,</p><p>don’t wear the word “security” like a borrowed coat.</p><p>You’re not a builder, you’re a shift on someone’s sand —</p><p>clock in, clock out, and never touch the plan.</p><br><h2 id="h-bridge" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Bridge</h2><p>A maker knows the ache of building something true.</p><p>You’ve never made a thing, so how would that get through?</p><p>I know. I know. It’s fine.</p><p>You wouldn’t recognise a signal if it screamed inside your name.</p><br><h2 id="h-outro" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Outro</h2><p>Reject it. Rename it. Ignore it.The sand does not care what you filed.</p><p>One tide, one line, one night —and the mirror is still there.</p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/f95080a6acc109639cd63acd5723a6300ddea5f2bb0e2e2ed33de00098f20c0f.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Music:The Logs Remain — I Turned a Rejected Bug Report Into a Track]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/the-logs-remain-i-turned-a-rejected-bug-report-into-a-track</link>
            <guid>GNYHHbio9DddGKtNALV0</guid>
            <pubDate>Thu, 06 Aug 2026 13:39:31 GMT</pubDate>
            <description><![CDATA[DJ ISHIJIMA / ALGORITHM MUSIC ▶ https://www.youtube.com/watch?v=jHF9swuj7ws Seven submissions. ~$400 in fees. $0 paid. This isn't an exposé. It's a release note. For the past several months I've been doing vulnerability research against the OP Stack. I filed seven-plus reports through Immunefi and paid roughly $400 in submission fees along the way. I received nothing. Four full rewrites. One report called "technically accurate" and closed anyway. Another forwarded to engineering, with no boun...]]></description>
            <content:encoded><![CDATA[<div data-type="youtube" videoid="jHF9swuj7ws">
      <div class="youtube-player" data-id="jHF9swuj7ws" style="background-image: url('https://i.ytimg.com/vi/jHF9swuj7ws/hqdefault.jpg'); background-size: cover; background-position: center">
        <a href="https://www.youtube.com/watch?v=jHF9swuj7ws">
          <img src="https://paragraph.com/editor/youtube/play.png" class="play">
        </a>
      </div></div><p><strong>DJ ISHIJIMA / ALGORITHM MUSIC</strong></p><p><span data-name="arrow_forward" class="emoji" data-type="emoji">▶</span> https://www.youtube.com/watch?v=jHF9swuj7ws</p><hr><h2 id="h-seven-submissions-dollar400-in-fees-dollar0-paid" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Seven submissions. ~$400 in fees. $0 paid.</h2><p>This isn't an exposé. It's a release note.</p><p>For the past several months I've been doing vulnerability research against the OP Stack. I filed seven-plus reports through Immunefi and paid roughly $400 in submission fees along the way. I received nothing.</p><p>Four full rewrites. One report called "technically accurate" and closed anyway. Another forwarded to engineering, with no bounty attached. When I was told impact wasn't proven, I mapped the extraction path and came back. When I was told it was out of scope, I came back with the citation. Then the reason changed again: no new issue.</p><p>That experience is one line in the song:</p><blockquote><p>"Goalposts moving like chain reorganization."</p></blockquote><p>That's my subjective read as the person paying to file. I haven't proven that any individual triage decision was made in bad faith, and I'm not claiming to. But what the process looks like <strong>from the paying side of the window</strong> seemed worth putting on the record.</p><hr><h2 id="h-why-a-track-instead-of-another-rewrite" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why a track instead of another rewrite</h2><p>I've been an audio engineer for 31 years. I build DX systems at a printing company in Tokyo. At night I do security research. Those three layers never touched each other.</p><p>Then one night I was drafting the fourth rewrite and my hands stopped. I had already spent every technical argument I had. What was left wasn't technical. It was <strong>emotional</strong> — and I only know one place to put that.</p><p>So this isn't retaliation. It's processing. I just changed where the logs get written.</p><hr><h2 id="h-about-the-track" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">About the track</h2><p>Cyberpunk hip-hop. It opens on a BOOT SEQUENCE and, in the GLITCH BREAK, raps the audit procedure itself:</p><blockquote><p>Claimed. Measured. Compare the two. If they don't match, the payload isn't true. Document. Reproduce. Verify. Review. Protect the user. Follow the proof.</p></blockquote><p>That's the one section with zero metaphor in it, because it isn't a metaphor. Compare the claimed value against the measured one. If they diverge, reject. Document, reproduce, verify, review. Protect the user. Follow the proof.</p><p>On the two companies named in the hook, one thing needs saying plainly: those lines are <strong>the voice of the narrator</strong>, not a legal allegation. I made no threat and I ran no attack. The lyrics say so themselves.</p><blockquote><p>No threat, no hack—this is a verbal audit.</p></blockquote><hr><h2 id="h-a-correction-on-the-record" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">A correction, on the record</h2><p>Credibility requires this part too.</p><p>One of the findings I considered central to this research was an asymmetry in refund validation in <code>alloy-op-evm</code>. After working through the documentation in <code>refund.rs</code>, I confirmed the behavior is <strong>intentional by design</strong>. I withdrew the claim and sent a correction to triage.</p><p>Retracting isn't a failure of research. It <em>is</em> research. Anyone who can't kill their own finding was never worth believing in the first place.</p><p>And the reason I'm still releasing this track hasn't changed, because the song was never really about whether that one finding held up. It's about a narrower question: <strong>when you pay a fee to submit, how much of the reasoning behind the decision are you entitled to see?</strong></p><hr><h2 id="h-the-verse-that-actually-matters" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The verse that actually matters</h2><p>The part I most wanted to write isn't the hook. It's Verse 3.</p><blockquote><p>To every researcher awake at four, With a passing test and a closed report: Rejection is paperwork—not natural law.</p></blockquote><p>Rejection is paperwork. It is not a law of nature. If your test passed, it still passes today, regardless of who clicked close.</p><p>Tokyo at 4am. São Paulo at dawn. Berlin. Nairobi. Someone is staring at the same screen at the same hour. You are not the rejection. You are not their decision. You're the one who looked when the system wouldn't listen.</p><hr><h2 id="h-a-note-for-anyone-listening-from-inside-the-same-situation" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">A note for anyone listening from inside the same situation</h2><p>This song does not allege criminal conduct by any company. It amplifies the <strong>subjective experience</strong> of submitting into a bounty program, through a fictional narrator.</p><p>If you're in that situation right now, take this over the lyrics. Facts before fury. Keep every message. Timestamp every claim. Manufacture nothing. Blame no one anonymously.</p><blockquote><p>Facts over fury, precision over fame.</p></blockquote><p>That's all of it. The logs remain.</p><hr><p><strong>DJ ISHIJIMA</strong> / ALGORITHM MUSIC #AlgorithmMusic #Web3 #BugBounty #Cyberpunk #SecurityResearch</p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/6c939787d1302eab17a8174172173be93e3957551ba1bc758bf3f2abc5e4f30b.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[How Optimism Claimed a Pre-Lagoon "Fix" While Leaving the Vulnerability Wide Open]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/howoptimismclaimedapre-lagoonfix</link>
            <guid>IF11CDbKzlxifsrL9VfS</guid>
            <pubDate>Sat, 01 Aug 2026 04:11:17 GMT</pubDate>
            <description><![CDATA[Do Not Present an Unverified Critical-Fix Narrative as Fact Core issue: Do not describe a “critical vulnerability fixed before exploitation” as an Optimism security success story when the fixing commit, information source, attribution, and relationship to the still-disputed reports have not been publicly established. This post is not primarily a request for another private review of my reports. It is a demand that OP Labs, the Optimism Foundation, and Immunefi stop allowing an inaccurate publ...]]></description>
            <content:encoded><![CDATA[<h1 id="h-do-not-present-an-unverified-critical-fix-narrative-as-fact" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Do Not Present an Unverified Critical-Fix Narrative as Fact</strong></h1><blockquote><p><strong>Core issue:</strong> Do not describe a “critical vulnerability fixed before exploitation” as an Optimism security success story when the fixing commit, information source, attribution, and relationship to the still-disputed reports have not been publicly established.</p></blockquote><p>This post is <strong>not primarily a request for another private review</strong> of my reports. It is a demand that <strong>OP Labs</strong>, the <strong>Optimism Foundation</strong>, and <strong>Immunefi</strong> stop allowing an inaccurate public narrative to stand.</p><p>After my governance disclosure, a story appeared in which Optimism discovered and fixed a “critical” vulnerability before exploitation. But the public record does not establish:</p><ul><li><p><strong>Who supplied the information used by the articles.</strong></p></li><li><p><strong>Whether the articles relied on my governance post, another private report, an Optimism statement, or an automated summary.</strong></p></li><li><p><strong>Who first reported each underlying technical finding.</strong></p></li><li><p><strong>Which exact commit supposedly fixed the reported defect.</strong></p></li><li><p><strong>Whether the Verify-path defect described in my post was actually fixed.</strong></p></li></ul><p>What is established is that my reports were closed, I received no bounty or refund, and my substantive communications remain unanswered.</p><p>The chronology and technical overlap create a serious provenance question, but they do not answer it. That is precisely why an unverified success narrative should not be presented as established fact.</p><p>The eight closed reports and their contradictory explanations matter because they establish the record behind that public narrative.</p><p>I am <strong>not</strong> asking the community to accept my original severity estimates without examination. During my investigation, I corrected and narrowed several of my own claims when later testing did not support them.</p><p>What I am asking for is much simpler:</p><p><strong>If a report is technically wrong, identify the precise error. If it is a duplicate, identify the earlier report and timestamp. If it was already fixed, identify the fixing commit. If it was out of scope, identify the exact published rule in force on the submission date.</strong></p><p>I initially assumed that, as a new security researcher, I had misunderstood the program rules. I investigated the rejection reasons so that I could improve my future reports. Instead, I repeatedly found public code and official statements that contradicted or materially qualified the explanations I had received.</p><p>That is why a further private and unexplained decision is not sufficient. <strong>The inaccurate public record requires a public answer and, if unsupported, a public correction.</strong></p><hr><h2 id="h-1-the-documented-report-history" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>1. The documented report history</strong></h2><table><colgroup><col><col><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p><strong>Report</strong></p></th><th colspan="1" rowspan="1"><p><strong>Submitted</strong></p></th><th colspan="1" rowspan="1"><p><strong>Closed</strong></p></th><th colspan="1" rowspan="1"><p><strong>Recorded reason</strong></p></th></tr><tr><td colspan="1" rowspan="1"><p><strong>#82258</strong></p></td><td colspan="1" rowspan="1"><p>June 18, 04:15</p></td><td colspan="1" rowspan="1"><p>June 18, 04:32</p></td><td colspan="1" rowspan="1"><p>Claimed impact out of scope; asset and severity stated to be in scope</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#82416</strong></p></td><td colspan="1" rowspan="1"><p>June 19, 18:46</p></td><td colspan="1" rowspan="1"><p>June 19, 18:56</p></td><td colspan="1" rowspan="1"><p>Critical consequences marked “NOT PROVEN”; insufficient live fault-proof evidence</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#82517</strong></p></td><td colspan="1" rowspan="1"><p>June 20, 23:21</p></td><td colspan="1" rowspan="1"><p>June 21, 06:38</p></td><td colspan="1" rowspan="1"><p>Changed input producing a changed root was not considered a soundness defect; alloy-op-evm and Kona said not to be listed assets</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#83109</strong></p></td><td colspan="1" rowspan="1"><p>June 26, 15:39</p></td><td colspan="1" rowspan="1"><p>June 26, 15:55</p></td><td colspan="1" rowspan="1"><p>Impact and asset in scope; severity out of scope</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#83447</strong></p></td><td colspan="1" rowspan="1"><p>June 30, 04:06</p></td><td colspan="1" rowspan="1"><p>June 30, 19:59</p></td><td colspan="1" rowspan="1"><p>The cited <code>op-chain-ops/pkg/sdm/workload.go</code> was said not to exist</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#83583</strong></p></td><td colspan="1" rowspan="1"><p>July 1, 15:24</p></td><td colspan="1" rowspan="1"><p>July 2, 19:52</p></td><td colspan="1" rowspan="1"><p>It was subsequently acknowledged that <code>workload.go:313</code> contained the recompute/equality check I described, but a consensus split was said not to be established</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#83996</strong></p></td><td colspan="1" rowspan="1"><p>July 5, 23:34</p></td><td colspan="1" rowspan="1"><p>July 7, 04:58</p></td><td colspan="1" rowspan="1"><p>The code-level asymmetry was acknowledged as technically accurate, but Lagoon was not active on a production chain</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>#84638</strong></p></td><td colspan="1" rowspan="1"><p>July 13, 13:52</p></td><td colspan="1" rowspan="1"><p>July 14, 16:37</p></td><td colspan="1" rowspan="1"><p>Treated as reconsideration of previous reports rather than a new vulnerability</p></td></tr></tbody></table><p><strong>All eight reports were closed. None was labelled “Duplicate,” and no bounty or refund was paid.</strong></p><p>Some decisions were made extremely quickly:</p><ul><li><p>#82258 was closed after <strong>17 minutes</strong>.</p></li><li><p>#82416 was closed after <strong>10 minutes</strong>.</p></li><li><p>#83109 was closed after <strong>16 minutes</strong>, after a 50 USDC submission payment.</p></li></ul><p>Speed alone does not prove that a review was inadequate. It does, however, make verifiable reasoning and exact references especially important.</p><hr><h2 id="h-2-a-concrete-contradiction-in-the-closure-explanations" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>2. A concrete contradiction in the closure explanations</strong></h2><p>Report <strong>#83447</strong> was rejected with this statement:</p><blockquote><p>“the cited Go enforcement at op-chain-ops/pkg/sdm/workload.go does not exist in the codebase”</p></blockquote><p>In the following report, <strong>#83583</strong>, the response stated:</p><blockquote><p>“Line 313 in op-chain-ops/pkg/sdm/workload.go is indeed a recompute-equality check … exactly as you described”</p></blockquote><p>These statements concern the <strong>same file and the same check</strong>.</p><p>I have not received a correction or explanation for the first statement. If the initial rejection resulted from reviewing the wrong branch, revision, or repository state, please identify what was reviewed and correct the record.</p><hr><h2 id="h-3-already-exists-was-asserted-without-identifying-an-equivalent-consensus-check" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>3. “Already exists” was asserted without identifying an equivalent consensus check</strong></h2><p>The response to <strong>#82517</strong> stated:</p><blockquote><p>“The recompute-and-compare logic the report recommends already exists in the selected in-scope asset rust/op-reth”</p></blockquote><p>The response referred generally to <code>post-exec-replay</code>, but did not identify the precise <code>op-reth</code> file and line that supposedly performed the equivalent consensus rejection.</p><p>I later located:</p><p><code>rust/op-reth/crates/post-exec-replay/src/replay.rs</code></p><p>That component is described as a <strong>debugging/counterfactual replay tool</strong>. It uses <code>PostExecMode::Produce</code>, can record mismatches in a vector, and returns a replay result containing those mismatches.</p><p>That is not obviously equivalent to having the consensus <code>PostExecMode::Verify</code> path reject an invalid producer-supplied refund.</p><p><strong>If another implementation performs that consensus-enforced comparison, please provide the exact repository, commit, file, line, and test.</strong></p><hr><h2 id="h-4-the-lagoon-explanation-and-the-published-pre-production-scope" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>4. The Lagoon explanation and the published pre-production scope</strong></h2><p>For <strong>#83996</strong>, Immunefi wrote:</p><blockquote><p>“The report describes a real code-level asymmetry.”</p></blockquote><p>and:</p><blockquote><p>“This is a technically accurate observation about the code.”</p></blockquote><p>The report was nevertheless closed because Lagoon was <code>ForkCondition::Never</code> on the named production chains and the behavior was therefore not exploitable on a production chain at that time.</p><p>However, Optimism had publicly announced that its bounty program was being extended to cover proposed protocol upgrades <strong>before they go into production</strong>:</p><p><a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://optimism.io/blog/optimism-extends-2-million-bug-bounty-program-to-protocol-upgrades-ahead-of-superchain-interop">Optimism Extends $2 Million Bug Bounty Program to Protocol Upgrades Ahead of Superchain Interop</a></p><p>The public repository also showed:</p><ul><li><p>SDM marked as a code-complete milestone in <a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://github.com/ethereum-optimism/optimism/issues/20452">issue #20452</a>.</p></li><li><p>SDM gated directly on the Lagoon hardfork in <a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://github.com/ethereum-optimism/optimism/pull/21105">PR #21105</a>.</p></li><li><p>Public work coordinating the <code>interop_time</code> to <code>lagoon_time</code> rename in <a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://github.com/ethereum-optimism/optimism/issues/21135">issue #21135</a>.</p></li><li><p>Lagoon scheduling support in the deployment configuration in <a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://github.com/ethereum-optimism/optimism/pull/21148">PR #21148</a>.</p></li></ul><p>I am <strong>not</strong> claiming that SDM was part of the Upgrade 16 payload or already active on OP Mainnet. My question is narrower:</p><blockquote><p><strong>What exact published rule, effective on the submission date, excluded implemented but not-yet-activated protocol-upgrade code from the announced pre-production bounty coverage?</strong></p></blockquote><p>“Not active on production” does not, without further explanation, resolve that question when the public program expressly invited research into upgrades before production.</p><hr><h2 id="h-5-the-unresolved-attribution-and-chronology-around-82258-and-pr-21434" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>5. The unresolved attribution and chronology around #82258 and PR #21434</strong></h2><p>Report <strong>#82258</strong> was submitted at <strong>04:15 UTC on June 18</strong> and closed at <strong>04:32 UTC</strong>.</p><p>Later that day, <a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://github.com/ethereum-optimism/optimism/pull/21434">PR #21434</a> was merged. Its description refers to Immunefi report <strong>#81847</strong>.</p><p>PR #21434 describes, among other things:</p><ul><li><p>Fee-vault settlement touches claiming a rebate.</p></li><li><p>Caller, target, and created addresses claiming a rebate because they were intrinsically warm.</p></li></ul><p>These are also specific phantom-refund causes described in #82258.</p><p>This chronology and content overlap do <strong>not</strong>, by themselves, prove unauthorized use. They do require a transparent provenance review.</p><p>I therefore request:</p><ol><li><p>The submission timestamp and relevant technical contents of #81847.</p></li><li><p>A timestamped comparison of #81847 and #82258.</p></li><li><p>An explanation of why #82258 was closed as out of scope instead of being classified as a duplicate, if #81847 already contained the same finding.</p></li><li><p>Confirmation of which report supplied each technical finding implemented by PR #21434.</p></li><li><p>Correction of the public credit if the timestamped records show that attribution is incomplete.</p></li></ol><p>Because the reports are private, only Optimism and Immunefi currently possess the records necessary to resolve this question conclusively.</p><hr><h2 id="h-6-an-unverified-critical-fix-narrative-presented-as-an-optimism-success-story" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>6. An unverified critical-fix narrative presented as an Optimism success story</strong></h2><p>This is the most serious issue of <strong>governance integrity and compliance</strong>.</p><p>An official governance forum should serve as a record of public accountability. After my disclosure appeared there, a success narrative emerged in which Optimism discovered and fixed a <strong>“critical” vulnerability before exploitation</strong>. However, no exact fixing commit has been identified, the information source has not been disclosed, and the relationship between that narrative and the disputed private reports remains unknown.</p><p>Examples include:</p><ul><li><p><a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://www.kucoin.com/ja/news/flash/optimism-patches-critical-pre-lagoon-refund-bug-before-production-no-funds-lost">KuCoin coverage</a></p></li><li><p><a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://bitcoinist.com/optimism-discloses-critical-pre-lagoon-vulnerability-that-was-patched-before/">Bitcoinist coverage</a></p></li><li><p><a target="_blank" rel="noopener nofollow ugc" class="dont-break-out" href="https://guavy.com/wire/crypto/optimism-discloses-critical-vulnerability-before-lagoon-upgrade-6UKzk4gmXDIsxBOalibD9g">Guavy coverage</a></p></li></ul><p>My governance post identifies <strong>me as the author of that post</strong> and states that the underlying Verify-path issue remained unresolved. That proves neither that I was the first reporter of every overlapping technical point nor that the articles used my post as their source.</p><p>Likewise, the present public record does not prove that the articles relied on #81847, on information supplied by Optimism, or on an automated aggregation process. <strong>The source is unknown and should be disclosed.</strong></p><p>PR #21434 addressed particular phantom-rebate sources. I have not found a change there that makes <code>verifier_post_exec_refund_for_tx</code> recompute and compare the producer-supplied refund in the consensus Verify path.</p><p>A disputed and unresolved technical record must not be converted into corporate security publicity without establishing its source, attribution, and actual fixing commit.</p><p>If that occurred here, it is not merely a dispute over bounty eligibility. It is a serious failure of <strong>attribution, transparency, governance integrity, and compliance</strong> that the Collective must investigate publicly.</p><p>I therefore request that Optimism state publicly:</p><ul><li><p>Whether it considers the Verify-path issue fixed.</p></li><li><p>The exact fixing PR and commit.</p></li><li><p>Which organization or statement was the source for the media claim that it was patched.</p></li><li><p>Which report or disclosure first documented each technical finding, based on verifiable timestamps.</p></li><li><p>Whether the media reports accurately identify their source and the responsible researcher, if any.</p></li><li><p>Whether a correction will be requested if those claims are inaccurate.</p></li></ul><p>I am not asserting, without source records, that Optimism supplied the information to these publications or that I am necessarily the original reporter of every overlapping point. I am stating that the published success narrative cannot presently be verified from the governance post, private-report references, and code history available to the public.</p><hr><h2 id="h-7-what-my-current-technical-evidence-establishesand-does-not-establish" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>7. What my current technical evidence establishes—and does not establish</strong></h2><p>My current tests establish the following narrower behavior:</p><ul><li><p>The SDM Verify path accepts a producer-supplied refund without independently recomputing it.</p></li><li><p>On an SDM-enabled development environment, a forged refund was accepted with a <code>VALID</code> payload result.</p></li><li><p>In a five-transaction test, the forged refund reduced expected fee income from <code>525,000,052,500,000 wei</code><strong> to zero</strong>.</p></li><li><p>The unpaid amount remained in the sender’s L2 balance.</p></li><li><p>I separately demonstrated initiating a withdrawal of retained L2 balance.</p></li></ul><p>I have also expressly withdrawn or limited claims that my evidence did not establish.</p><p>My present evidence does <strong>not</strong> establish:</p><ul><li><p>Theft of unrelated third-party principal.</p></li><li><p>A profit exceeding the malicious sender’s own transaction costs.</p></li><li><p>Completion of an L1 withdrawal using the same SDM-derived test balance.</p></li><li><p>A full real-Kona and permissionless FaultDisputeGame reproduction.</p></li></ul><p>These corrections are part of responsible research. They do not erase the separately demonstrated verification behavior or the need for a precise technical response.</p><hr><h2 id="h-8-payments-and-mediation" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>8. Payments and mediation</strong></h2><p>The payment history shows:</p><ul><li><p>Five Optimism submission payments of 50 USDC each: <strong>250 USDC total</strong>.</p></li><li><p>A separate 100 USDC identity-verification payment.</p></li><li><p>Two separate Wormhole submission payments totalling 50 USDC.</p></li></ul><p>The total platform payments shown are 400 USDC, but only <strong>250 USDC</strong> represents Optimism report-submission payments. There is no corresponding payment row in the available history for the first three Optimism reports.</p><p>No Optimism bounty or refund was paid.</p><p>I did <strong>not</strong> pay for or commence mediation.</p><p>The mediation interface for #84638 displayed:</p><ul><li><p>A free Standard queue, but stated that free mediation was unavailable for reports closed by the Immunefi team.</p></li><li><p>A further message stating that the project required Priority mediation.</p></li><li><p>Priority mediation priced at <strong>250 USDC</strong>.</p></li><li><p>A warning that payment would not influence the result and would not guarantee a favorable decision.</p></li></ul><p>Therefore, the official route proposed after closure was visible to me only as a paid 250 USDC option. I did not purchase it.</p><hr><h2 id="h-9-unanswered-communications" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>9. Unanswered communications</strong></h2><p>I preserved <strong>ten outgoing </strong><code>.eml</code><strong> files representing nine unique Message-IDs</strong>. They include communications sent to support and later expanded to information, contact, legal, and team addresses.</p><p>The preserved archive contains no incoming Immunefi email resolving the technical questions, attribution issue, or refund request.</p><p>There was one platform response from Customer Support on July 15. It referred me to mediation, mentioned my report-validity rating, and warned about publication rules. It did not answer the refund request or the technical contradictions listed above.</p><p>Subsequent requests recorded on the platform received no further substantive response through August 3.</p><hr><h2 id="h-10-the-effect-on-the-researcher" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>10. The effect on the researcher</strong></h2><p>I initially believed that these outcomes might simply reflect my inexperience with bug-bounty rules.</p><p>I therefore spent approximately one month reviewing code across multiple implementations and layers, reproducing behavior, preparing tests and proposed patches, and correcting my own claims where the evidence required it.</p><p>Instead of receiving explanations that allowed me to understand and improve, I repeatedly encountered reasons that could be contradicted or materially qualified using public GitHub code and Optimism’s own published materials.</p><p>This has seriously disrupted my work as an audio engineer and caused substantial psychological distress.</p><p>Compensation matters. But the more fundamental issue is receiving a <strong>coherent, evidence-based decision</strong>:</p><ul><li><p>If the report is technically wrong, identify the precise error.</p></li><li><p>If it is a duplicate, identify the earlier report and its timestamp.</p></li><li><p>If it was already fixed, identify the fixing commit.</p></li><li><p>If it was out of scope, identify the exact published rule that applied on the submission date.</p></li><li><p>If public credit is incorrect, correct it.</p></li><li><p>If a media report incorrectly says the vulnerability was fixed, identify the actual fix or request a correction.</p></li></ul><p>Researchers cannot investigate against secret rules.</p><hr><h2 id="h-required-public-correction-and-accountability" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>Required public correction and accountability</strong></h2><p>My principal request is not another opaque internal review. I require OP Labs, the Optimism Foundation, and Immunefi to address the public representation directly:</p><ol><li><p><strong>Stop representing the disclosure as an Optimism critical-fix success story unless that claim can be substantiated.</strong></p></li><li><p>Identify the exact PR and commit that fixed the defect described in my governance post.</p></li><li><p>Identify the source supplied to, or relied upon by, the publications that described the issue as patched.</p></li><li><p>Publish a timestamp-based attribution record identifying which report or researcher first supplied each relevant technical finding.</p></li><li><p>Request corrections from publications if the “patched before exploitation” claim or attribution is inaccurate.</p></li><li><p>Publish a timestamped comparison of #81847 and #82258 sufficient to resolve precedence and credit.</p></li><li><p>Correct the contradictory <code>workload.go</code> statements and provide the exact consensus code said to implement recompute-and-compare protection.</p></li><li><p>Identify the contemporaneous rule used to exclude #83996 despite the published pre-production-upgrade coverage.</p></li><li><p>Address bounty eligibility and the <strong>250 USDC</strong> in Optimism submission payments only after the public technical and attribution record has been corrected.</p></li><li><p>Provide a <strong>named, authorized contact</strong> and a substantive response.</p></li></ol><p>I am not publishing private exploit parameters in this post. I am prepared to provide the preserved reports, receipts, email files, hashes, code references, and test materials through an authorized channel.</p><p>I do not want another generic instruction to submit a new report, purchase mediation, or wait for an unspecified internal review. <strong>I want the unsupported success narrative stopped and the public record corrected.</strong></p><blockquote><p><strong>Honor the rules and representations you publish. If they cannot be honored, do not ask researchers to rely on them.</strong></p></blockquote><p>Continued silence does not resolve these issues. Its practical effect is to leave the researcher with no accessible review path except to abandon the matter.</p><p>I am asking publicly whether that is the intended outcome—and, if it is not, who will take responsibility for resolving this record.</p><p>Perhaps I can say this precisely because I am an engineer from another industry: <strong>if other researchers already know that such opaque and unreasonable treatment occurs, why has it been allowed to remain unspoken?</strong></p><p>I am writing this in the sincere hope that the many diligent and talented researchers who may have endured the same frustration will no longer be forced into silence, and will finally receive the <strong>recognition and fair treatment they deserve</strong>.</p><blockquote><p><strong>Separately, I have already sent emails concerning another time-sensitive security matter. I am genuinely concerned about it, and I strongly urge OP Labs and Immunefi to review and respond to those emails as soon as possible.</strong></p></blockquote><p>— <strong>Yomibito Shirazu / Yohei Ishijima</strong></p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <category>eth</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/f0384170ac2e1d6d08e417677e2d057288318e99c730766819632cd88c2647d6.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[How I Found a Forged-Refund Backdoor in Optimism's SDM — and What Happened Next]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/how-i-found-a-forged-refund-backdoor-in-optimisms-sdm-and-what-happened-next</link>
            <guid>Z20bLfELCeR9C1d2OC7r</guid>
            <pubDate>Tue, 21 Jul 2026 15:00:00 GMT</pubDate>
            <description><![CDATA[詠み人知らず — Yomibito shirazu. An old Japanese word for the author of a poem whose name has been lost to time, yet whose truth has been passed down through generations. The identity is unknown. The truth remains. The Summary There is a backdoor in Optimism's upcoming SDM (Sequencer-Defined Mechanics) system. A malicious sequencer can forge gas refund values that every verifier accepts without recomputation. The same forged values are written as a state root to L1. Optimism's fault-proof system — ...]]></description>
            <content:encoded><![CDATA[<div data-type="x402Embed"></div><blockquote><p><strong>詠み人知らず</strong> — <em>Yomibito shirazu.</em> An old Japanese word for the author of a poem whose name has been lost to time, yet whose truth has been passed down through generations. The identity is unknown. The truth remains.</p></blockquote><hr><h2 id="h-the-summary" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Summary</h2><p>There is a backdoor in Optimism's upcoming SDM (Sequencer-Defined Mechanics) system. A malicious sequencer can forge gas refund values that every verifier accepts without recomputation. The same forged values are written as a state root to L1. Optimism's fault-proof system — kona — cannot dispute it, because kona replicates the same forged root.</p><p>The bug is pre-production. Lagoon has not yet activated on any mainnet. No funds have been lost.</p><p>I reported this to Immunefi. I was rejected twice — not on technical grounds, but on scope grounds. In June 2025, Optimism explicitly extended its $2 million bug bounty to cover pre-production protocol upgrades.</p><p>This is the story of what I found, what I was told, and what I am doing about it.</p><hr><h2 id="h-my-background" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">My Background</h2><p>I am a sound engineer. I have been programming since I was 14 — this is my 31st year.</p><p>In my field, asymmetry means death. When one side of a system measures and the other side trusts without verification, equipment fails. People get hurt. You learn to treat asymmetry as an alarm, not a design choice.</p><p>When I read the SDM code, the Produce path measured gas refunds locally using an inspector. The Verify path read the producer's value and applied a size cap. No recomputation. To me, that asymmetry was not a design choice. It was a fire alarm.</p><p>The core developer said it was "by design."<br>Thirty-one years of engineering said otherwise.</p><hr><h2 id="h-background-optimisms-sdm" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Background: Optimism's SDM</h2><p>Optimism's SDM (Sequencer-Defined Mechanics) is a new system that allows the sequencer to define custom gas accounting behavior per transaction — warming rebates, refunds, fee adjustments. The sequencer publishes these values alongside the block; verifiers and the fault-proof system consume them.</p><p>SDM has two execution modes:</p><pre data-type="codeBlock" text="PRODUCE (sequencer)                    VERIFY (verifier / kona)
─────────────────────                  ────────────────────────
Run EVM with inspector                 Read producer-supplied payload
Inspector measures refund locally  →   Apply size cap: refund ≤ evm_gas_used
Write to post_exec payload             Accept value — NO RECOMPUTATION
        ↓                                      ↓
  Trustworthy                            Trusts the sequencer
"><code>PRODUCE (sequencer)                    VERIFY (verifier / kona)
─────────────────────                  ────────────────────────
Run EVM with inspector                 Read producer-supplied payload
Inspector measures refund locally  →   Apply size cap: refund ≤ evm_gas_used
Write to post_exec payload             Accept value — NO RECOMPUTATION
        ↓                                      ↓
  Trustworthy                            Trusts the sequencer
</code></pre><p>This asymmetry is the bug.</p><p>SDM is gated on the Lagoon hardfork (<code>lagoon_time</code>). As of this writing, <code>lagoon_time</code> is <code>None</code> on all production chains. The code is complete. The hardfork has not yet activated.</p><hr><h2 id="h-the-defect" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Defect</h2><p>The Verify path in <code>rust/alloy-op-evm/src/block/mod.rs</code>:</p><pre data-type="codeBlock" text="let Some(refund) = self.post_exec.verifier_refund(tx_index) else { return Ok(0); };
if refund &gt; evm_gas_used { return Err(...) }  // size cap only
Ok(refund)                                     // producer value accepted — no recompute
"><code>let Some(refund) <span class="hljs-operator">=</span> <span class="hljs-built_in">self</span>.post_exec.verifier_refund(tx_index) <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> Ok(<span class="hljs-number">0</span>); };
<span class="hljs-keyword">if</span> refund <span class="hljs-operator">&gt;</span> evm_gas_used { <span class="hljs-keyword">return</span> Err(...) }  <span class="hljs-comment">// size cap only</span>
Ok(refund)                                     <span class="hljs-comment">// producer value accepted — no recompute</span>
</code></pre><p>The only guard is <code>refund &lt;= evm_gas_used</code>. A malicious sequencer sets <code>refund = evm_gas_used</code> for every transaction. Every verifier accepts it.</p><h3 id="h-how-the-sequencer-profits" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">How the Sequencer Profits</h3><p>Here is the attack, step by step:</p><ol><li><p>Sequencer produces a block. For each transaction, it sets <code>gas_refund = evm_gas_used</code> in the SDM payload — the maximum value the size cap allows.</p></li><li><p>The actual warming refund is a fraction of <code>evm_gas_used</code>. The difference is the forged amount.</p></li><li><p><code>post_exec_settlement_deltas</code> processes the payload:</p><ul><li><p>Credits the sequencer's L2 balance by <code>forged_refund × effective_gas_price</code></p></li><li><p>Debits fee recipients (L1 fee vault, base fee vault) by the same amount</p></li></ul></li><li><p>The resulting <code>state_root</code> — computed over the forged balances — is committed to L1.</p></li></ol><p>The sequencer extracts value from fee recipients on every block, invisibly, at the maximum rate the size cap allows. On a busy chain with high gas prices, this compounds rapidly.</p><h3 id="h-the-kona-dimension" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The Kona Dimension</h3><p>kona is Optimism's fault-proof client. When a challenger disputes a block, kona re-executes it and computes the expected state root.</p><p>kona shares the same non-recomputing Verify code path (<code>core.rs:310</code>). When kona re-executes the forged block, it reads the same forged SDM payload, applies the same size-cap-only check, and arrives at the same forged state root.</p><p>The challenger's root matches the sequencer's root.</p><p><strong>There is nothing to dispute.</strong> The fraud-proof system is structurally blind to this manipulation.</p><hr><h2 id="h-proof-of-concept" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Proof of Concept</h2><p>Drop this into <code>rust/alloy-op-evm/src/block/tests.rs</code>, module <code>sdm</code>. Run:</p><pre data-type="codeBlock" text="cargo test --manifest-path rust/Cargo.toml -p alloy-op-evm --lib \
  block::tests::sdm::poc_verify_accepts_forged_refund_without_recompute -- --nocapture
"><code>cargo test <span class="hljs-operator">-</span><span class="hljs-operator">-</span>manifest<span class="hljs-operator">-</span>path rust<span class="hljs-operator">/</span>Cargo.toml <span class="hljs-operator">-</span>p alloy<span class="hljs-operator">-</span>op<span class="hljs-operator">-</span>evm <span class="hljs-operator">-</span><span class="hljs-operator">-</span>lib \
  <span class="hljs-built_in">block</span>::tests::sdm::poc_verify_accepts_forged_refund_without_recompute <span class="hljs-operator">-</span><span class="hljs-operator">-</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>nocapture
</code></pre><pre data-type="codeBlock" text="#[test]
fn poc_verify_accepts_forged_refund_without_recompute() {
    let target = Address::from([0x11; 20]);

    // --- Produce path: measure legitimate refund ---
    let mut f0 = SDMExecutorFixture::default();
    let mut producer = f0.executor_with_post_exec_mode(PostExecMode::Produce);
    producer.execute_transaction(&amp;legacy_tx(0, target)).expect(&quot;tx0&quot;);
    producer.execute_transaction(&amp;legacy_tx(1, target)).expect(&quot;tx1&quot;);
    let legit = producer
        .post_exec_entries()
        .iter()
        .find(|e| e.index == 1)
        .map(|e| e.gas_refund)
        .unwrap_or(0);
    drop(producer);

    // --- Verify path: inject forged refund ---
    const FORGED: u64 = 21_000;
    let mut f1 = SDMExecutorFixture::default();
    let verifier = f1.verifier(0, vec![SDMGasEntry { index: 1, gas_refund: FORGED }]);
    let accepted = verifier
        .verifier_post_exec_refund_for_tx(1, false, false, 21_000)
        .expect(&quot;Verify accepts forged refund (no recompute)&quot;);

    assert_eq!(accepted, FORGED);
    assert!(FORGED &gt; legit, &quot;forged {FORGED} must exceed legit {legit}&quot;);
    println!(&quot;VERIFY-NO-RECOMPUTE | accepted={accepted} legit={legit}&quot;);
}
"><code>#[test]
fn poc_verify_accepts_forged_refund_without_recompute() {
    let target <span class="hljs-operator">=</span> Address::<span class="hljs-keyword">from</span>([<span class="hljs-number">0x11</span>; <span class="hljs-number">20</span>]);

    <span class="hljs-comment">// --- Produce path: measure legitimate refund ---</span>
    let mut f0 <span class="hljs-operator">=</span> SDMExecutorFixture::default();
    let mut producer <span class="hljs-operator">=</span> f0.executor_with_post_exec_mode(PostExecMode::Produce);
    producer.execute_transaction(<span class="hljs-operator">&amp;</span>legacy_tx(<span class="hljs-number">0</span>, target)).expect(<span class="hljs-string">"tx0"</span>);
    producer.execute_transaction(<span class="hljs-operator">&amp;</span>legacy_tx(<span class="hljs-number">1</span>, target)).expect(<span class="hljs-string">"tx1"</span>);
    let legit <span class="hljs-operator">=</span> producer
        .post_exec_entries()
        .iter()
        .find(<span class="hljs-operator">|</span>e<span class="hljs-operator">|</span> e.index <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>)
        .map(<span class="hljs-operator">|</span>e<span class="hljs-operator">|</span> e.gas_refund)
        .unwrap_or(<span class="hljs-number">0</span>);
    drop(producer);

    <span class="hljs-comment">// --- Verify path: inject forged refund ---</span>
    const FORGED: u64 <span class="hljs-operator">=</span> <span class="hljs-number">21_000</span>;
    let mut f1 <span class="hljs-operator">=</span> SDMExecutorFixture::default();
    let verifier <span class="hljs-operator">=</span> f1.verifier(<span class="hljs-number">0</span>, vec<span class="hljs-operator">!</span>[SDMGasEntry { index: <span class="hljs-number">1</span>, gas_refund: FORGED }]);
    let accepted <span class="hljs-operator">=</span> verifier
        .verifier_post_exec_refund_for_tx(<span class="hljs-number">1</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, <span class="hljs-number">21_000</span>)
        .expect(<span class="hljs-string">"Verify accepts forged refund (no recompute)"</span>);

    assert_eq<span class="hljs-operator">!</span>(accepted, FORGED);
    <span class="hljs-built_in">assert</span><span class="hljs-operator">!</span>(FORGED <span class="hljs-operator">&gt;</span> legit, <span class="hljs-string">"forged {FORGED} must exceed legit {legit}"</span>);
    println<span class="hljs-operator">!</span>(<span class="hljs-string">"VERIFY-NO-RECOMPUTE | accepted={accepted} legit={legit}"</span>);
}
</code></pre><p>The test passes. The Verify path accepts the forged value without complaint.</p><hr><h2 id="h-pr-21434-why-it-is-not-enough" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">PR #21434: Why It Is Not Enough</h2><p>PR #21434 addresses a related issue: top-level account touches that could over-refund. One sentence explains why it is insufficient:</p><blockquote><p>PR #21434 adds guards at the account level. It does not add recomputation to the Verify path. <code>verifier_post_exec_refund_for_tx</code> is unchanged.</p></blockquote><p>Commits <code>242a4e6</code> and <code>cfbc098</code> confirm this in <code>main</code> after the PR merged.</p><p>There is also a secondary issue: inner <code>CREATE</code> calls (depth &gt; 0) in <code>inspector.rs</code> are not excluded from warming rebate accounting — the same class of bug #21434 addressed at the top level, but at depth.</p><hr><h2 id="h-the-fix" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Fix</h2><pre data-type="codeBlock" text="let recomputed = self.inspector.recompute_warming_refund(tx_index);
if claimed != recomputed {
    return Err(Self::invalid_post_exec_payload(&quot;refund mismatch&quot;));
}
"><code>let recomputed <span class="hljs-operator">=</span> <span class="hljs-built_in">self</span>.inspector.recompute_warming_refund(tx_index);
<span class="hljs-keyword">if</span> claimed <span class="hljs-operator">!</span><span class="hljs-operator">=</span> recomputed {
    <span class="hljs-keyword">return</span> Err(Self::invalid_post_exec_payload(<span class="hljs-string">"refund mismatch"</span>));
}
</code></pre><p><code>debug_replaySDMBlock</code> in <code>workload.go:313</code> already implements equivalent logic. The Verify path should do the same.</p><hr><h2 id="h-pr-20452-in-active-development" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">PR #20452: "In Active Development"</h2><p>When I contacted an Optimism core developer about this, I was told SDM is "in active development" and suggested the bug may not be worth reporting yet.</p><p>PR #20452 — the SDM Code Complete milestone — was closed on June 18, 2026. By the same developer.</p><hr><h2 id="h-the-bounty-story" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Bounty Story</h2><p>I came to this casually. I found an asymmetry in the code, wrote a PoC, and submitted it to Immunefi. I had no prior experience with bug bounties. When my first report was rejected, I assumed I had misunderstood the rules. So I read the rules again, rewrote the report, and submitted again.</p><p>Then again. Then again.</p><p>By the seventh submission, I had paid $400 in fees and rewritten the report from scratch four times. I had added kona traces, economic impact calculations, a 7-point formal rebuttal of every rejection ground, and a request for Immunefi mediation. The mediation request was also ignored.</p><p>At some point, I stopped wondering what I was doing wrong. The system was doing something wrong.</p><p>I submitted this vulnerability to Immunefi seven times. I paid $400 in submission fees. Every report was closed as "invalid" or "out of scope." Not once as "duplicate." Not once with reference to a prior accepted report.</p><p>The rejection reasons shifted with each submission:</p><ul><li><p><em>"Impact not demonstrated"</em> — I added a complete kona E2E trace.</p></li><li><p><em>"Out of scope"</em> — I cited the June 2025 blog explicitly extending coverage to pre-production upgrades.</p></li><li><p><em>"No new vulnerability"</em> — My report was a reconsideration request, which they closed without reading.</p></li></ul><p>On report #83996, the triage team wrote: <strong>"yes — technically accurate"</strong> — and closed it anyway.</p><p>On report #83583, Immunefi wrote that <em>"the underlying observation that Verify does not independently recompute the refund has been forwarded to engineering as an informational hardening note for pre-activation SDM."</em></p><p>They forwarded my finding to engineering. They did not pay me.</p><p>In June 2025, Optimism published a blog post titled <em>"Optimism Extends $2 Million Bug Bounty Program to Protocol Upgrades Ahead of Superchain Interop"</em>. The post explicitly states:</p><blockquote><p><em>"In a first for Optimism and the industry, this bug bounty now includes calldata for protocol upgrades."</em></p></blockquote><p>My bug is in a protocol upgrade. It is pre-production. The extended bounty explicitly covers this.</p><p>Seven reports. $400. Technically accurate. Forwarded to engineering. Not paid.</p><p>A 7-point formal rebuttal, submitted to Immunefi mediation. Also ignored.</p><h3 id="h-economic-impact" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Economic Impact</h3><p>A dry-run with live OP Mainnet parameters shows the ceiling once Lagoon activates:</p><table><colgroup><col><col><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Scenario</p></th><th colspan="1" rowspan="1"><p>Base fee</p></th><th colspan="1" rowspan="1"><p>Effective gas price</p></th><th colspan="1" rowspan="1"><p>Protocol loss/day</p></th></tr><tr><td colspan="1" rowspan="1"><p>Lagoon stress (MAX)</p></td><td colspan="1" rowspan="1"><p>10 gwei</p></td><td colspan="1" rowspan="1"><p>30 gwei</p></td><td colspan="1" rowspan="1"><p><strong>17,280 ETH/day</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>Lagoon normal</p></td><td colspan="1" rowspan="1"><p>1 gwei</p></td><td colspan="1" rowspan="1"><p>1–30 gwei</p></td><td colspan="1" rowspan="1"><p>1,728 ETH/day</p></td></tr></tbody></table><p>At 17,280 ETH/day, the ETHLockbox is drainable in approximately 10 days.</p><hr><h2 id="h-the-precedent" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Precedent</h2><p>In 2022, Jay Freeman (saurik) discovered the selfdestruct/ETH-inflation bug in Optimism's OVM. In his own words:</p><blockquote><p><em>"Technically, their Immunefi program did not cover this bug, as it is not in the explicit scope, so I couldn't go through Immunefi and had to reach out directly. But they have been extremely gracious and immediately said they would cover it equivalently."</em></p></blockquote><p>Optimism paid saurik the full $2,000,042.</p><p>Saurik had no explicit written coverage. I have an Optimism-authored blog post that explicitly extends the bounty to pre-production upgrades.</p><p>The precedent is clear. My position is stronger than saurik's was.</p><hr><h2 id="h-timeline" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Timeline</h2><table><colgroup><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Date</p></th><th colspan="1" rowspan="1"><p>Event</p></th></tr><tr><td colspan="1" rowspan="1"><p>June 18, 2026</p></td><td colspan="1" rowspan="1"><p>PR #20452 (SDM Code Complete) closed</p></td></tr><tr><td colspan="1" rowspan="1"><p>June 2026</p></td><td colspan="1" rowspan="1"><p>Report #82258 submitted — closed: "invalid"</p></td></tr><tr><td colspan="1" rowspan="1"><p>June 2026</p></td><td colspan="1" rowspan="1"><p>Report #82416 submitted — closed: "invalid"</p></td></tr><tr><td colspan="1" rowspan="1"><p>June 21, 2026</p></td><td colspan="1" rowspan="1"><p>Report #82517 closed: "impact not demonstrated"</p></td></tr><tr><td colspan="1" rowspan="1"><p>June 2026</p></td><td colspan="1" rowspan="1"><p>Report #83109 closed: "out of scope"</p></td></tr><tr><td colspan="1" rowspan="1"><p>June 30, 2026</p></td><td colspan="1" rowspan="1"><p>Report #83447 closed: "invalid"</p></td></tr><tr><td colspan="1" rowspan="1"><p>July 2, 2026</p></td><td colspan="1" rowspan="1"><p>Report #83583 closed — Immunefi forwards finding to engineering as "informational hardening note"</p></td></tr><tr><td colspan="1" rowspan="1"><p>July 2026</p></td><td colspan="1" rowspan="1"><p>Report #83996 closed — triage confirms: <strong>"technically accurate"</strong></p></td></tr><tr><td colspan="1" rowspan="1"><p>July 14, 2026</p></td><td colspan="1" rowspan="1"><p>Report #84638 closed: "not a new vulnerability"</p></td></tr><tr><td colspan="1" rowspan="1"><p>July 20, 2026</p></td><td colspan="1" rowspan="1"><p>Pre-litigation notice sent to Immunefi</p></td></tr><tr><td colspan="1" rowspan="1"><p>July 22, 2026</p></td><td colspan="1" rowspan="1"><p>PoC sent directly to Optimism core developer</p></td></tr><tr><td colspan="1" rowspan="1"><p><strong>Total</strong></p></td><td colspan="1" rowspan="1"><p><strong>7 reports. $400 in fees. 0 payments.</strong></p></td></tr></tbody></table><hr><h2 id="h-a-word-from-the-author" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">A Word from the Author</h2><p><em>The following is my own statement, in my own language. I have provided a translation, but the original stands.</em></p><hr><p>インチキにもほどがある。不誠実にもほどがある。そして私はOPのユーザーだった。失望した。あまりにもひどい。</p><p>魔改造はいい、ワクワクするのはわかる。でも外しちゃいけないガードレールを外すな。そしてこんな危険なものをコピーして世界中で運営するな。悪意あるハッカーに狙われて当然。むしろ狙われることが仕様。いい加減にしろ。</p><p>これはユーザーとして、誠実なエンジニアとして、そして人間としてのまともな感覚だ。目を覚ませ。コア開発者たちよ。スピード競争の末路は砂の要塞を完成させるのか？バカバカしい。</p><p>隠蔽して喜んでるハリボテは必ずや崩壊すると予言する。これを許容するユーザーは自分のお金が無くなってもドブの中に入ってもいいというならば、ただちに飢餓で困っている人々、かわいそうな犬猫に寄付しろ。大馬鹿ものが。</p><p>トリアージは日本の伝説では餓鬼という、いつまでもお腹が満たされない鬼だ。まさにぴったりだ。</p><p>私の業界では絶対にこんなインチキは認められない。ユーザーが耳を傷めてしまうからだ。しかしお前らはプログラムの非対称という致命的な状態で置き去りにして、人生を傷めるものをマネーゲームと引き合いに黙殺している。これは絶対に何があってもどんなことがあっても許してはいけない。</p><hr><p><em>Translation:</em></p><p>There is a limit to dishonesty. There is a limit to insincerity. I was an OP user. I am disappointed. This is inexcusable.</p><p>Innovation is exciting — I understand that. But do not remove the guardrails that must never be removed. And do not copy something this dangerous and run it across the world. It is only natural that malicious hackers will target this. Being targeted is, in your own words, "by design." Enough.</p><p>This is the rational judgment of a user, of an honest engineer, and of a human being with basic moral sense. Wake up, core developers. Is the end of your speed race a fortress built on sand?</p><p>I prophesy that the hollow facade — the one that conceals and calls it complete — will surely collapse. If you are a user who accepts this, who is comfortable watching your money disappear into a ditch, then donate it immediately to people dying of hunger, to suffering animals. You are fools.</p><p>In Japanese legend, the triage team would be called <em>gaki</em> — hungry ghosts, creatures condemned to never be satisfied no matter how much they consume. The name fits perfectly.</p><p>In my industry, this kind of dishonesty is absolutely unacceptable. Because it injures the user's hearing. But you have left users behind in a fatally asymmetric codebase, and silenced the findings that could have protected their livelihoods — all in service of a money game. This must never be forgiven. Under any circumstances. Ever.</p><hr><h2 id="h-closing-thoughts" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Closing Thoughts</h2><p>A sound engineer does not ship asymmetric systems. The moment one side measures and the other side trusts, you have a single point of failure that the system cannot see.</p><p>Optimism built a sequencer that measures and verifiers that trust. They built a fault-proof system that replicates the same trust. And they shipped code-complete SDM into a codebase that will hold billions of dollars in value.</p><p>This is fixable. The fix is a one-function recomputation check. It should land before Lagoon activates on any production chain.</p><p>Saurik ended his disclosure with this:</p><blockquote><p><em>"We can also maybe feel good that the existence of this large bounty did what it set out to do: Optimism made a mistake, but they then incentivized—and quite generously so!—the work to correct it, protecting their users from loss."</em></p></blockquote><p>I hope to be able to write the same sentence.</p><p>This post will be updated with the resolution.</p><hr><p><em>Regression test, damage ceiling calculator, and full disclosure document available on request.</em></p><br>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/4587479195dec78d4a909a145d57be1b805ffe4868306d0aef1d11c08b269d2a.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Episode 3: The Guillotine]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/episode-3-the-guillotine</link>
            <guid>jYzugKbmBoRQPOSiDtdX</guid>
            <pubDate>Wed, 15 Jul 2026 00:55:08 GMT</pubDate>
            <description><![CDATA[All characters are anonymous. All events are speculation. You're reading the war room notes of a masked security researcher. Don't ask how I got these. 4:15 AM I clicked Submit at 4:15 in the morning. Not because I'm dramatic. Because I'd been writing the report for days straight, and at some point "one more pass" turns into "it's 4 AM and I'm still editing a comma." So I stopped editing and hit the button. The report was fourteen sections long. Root cause analysis. Affected components. Data ...]]></description>
            <content:encoded><![CDATA[<blockquote><p><em>All characters are anonymous. All events are speculation.</em> <em>You're reading the war room notes of a masked security researcher.</em> <em>Don't ask how I got these.</em></p></blockquote><hr><h3 id="h-415-am" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4:15 AM</h3><p>I clicked Submit at 4:15 in the morning.</p><p>Not because I'm dramatic. Because I'd been writing the report for days straight, and at some point "one more pass" turns into "it's 4 AM and I'm still editing a comma." So I stopped editing and hit the button.</p><p>The report was fourteen sections long. Root cause analysis. Affected components. Data flow diagram. Six PoC files — five for the honest-path phantom refund, one for the verifier validity failure. Two patch layers with test results. Economic modeling. Conservation proof. Terminal logs with commit hashes. Appendices A through D.</p><p>Everything I'd built in Episode 1 and 2. The two pitons, hammered into rock, tested under load. The whole climbing rig, packed and ready.</p><p>Here's what I was sure about: the bug was real. The Go verifier checks. The Rust verifier doesn't. Six PoCs prove it. The code is right there.</p><p>Here's what I didn't know: everything else. This was my first bug bounty submission. Ever. I'd never used Sentinel before. I'd never written a report in this format. I didn't know the unwritten rules — what to put in the title, how to phrase the severity claim, what triggers an instant closure, what makes a triager actually read past the first paragraph.</p><p>I was an audio engineer holding a sword, walking into a courthouse where I didn't know which door was the entrance and which was the guillotine.</p><p>But the bug was real. That had to be enough, right?</p><p>One thing I haven't mentioned. Sentinel charges you to play.</p><p>Registration: $100 USDC. That's the door fee. You pay it before you've submitted a single word.</p><p>And because I was new — no track record, no reputation, no prior accepted reports — I was classified as a low-tier researcher. Low-tier researchers pay an additional $50 deposit per submission. If the report is accepted, you get it back. If it's closed — for any reason, including "out of scope" — you don't.</p><p>I didn't know it at the time, but I would submit seven reports before this story was over. The first cost me $100. Each one after that, $50. Seven reports. $400.</p><p>That's what a freelance audio engineer between gigs pays for the privilege of having his vulnerability research closed in minutes, over and over and over. Not for bad research — for research that was right every time. $400 to feed the guillotine.</p><p>But I'm getting ahead of myself. This was report number one. And I still believed the system worked.</p><p>I submitted it through Sentinel — the bug bounty platform — targeting Horizon's program. Severity: Critical. Asset: the Rust execution client. Impact: canonical fee-accounting validity failure. Verifier accepts producer-asserted invalid refunds without legitimacy recomputation.</p><p>Fourteen sections. Six PoCs. Days of work.</p><p>I leaned back and opened a melon soda.</p><hr><h3 id="h-422-am" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4:22 AM</h3><p>Seven minutes later, a message appeared.</p><blockquote><p><em>"Hi, thanks for the submission. Your report is currently being reviewed by Sentinel. We will get back to you once a decision has been made."</em></p></blockquote><p>Standard acknowledgment. Automated, probably. Fine.</p><p>I took a sip of melon soda and started thinking about what to do while I waited. The review process usually takes days. Sometimes weeks. Complex reports with this much code need time — someone has to check out the commit, run the tests, read the analysis, verify the economic model, understand the two-layer fix.</p><p>I figured I'd hear back in a week. Maybe two.</p><hr><h3 id="h-432-am" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4:32 AM</h3><p>Ten minutes later, the status changed.</p><p><strong>CLOSED.</strong></p><p>I stared at the screen.</p><blockquote><p><em>"Hi, Sentinel has reviewed this vulnerability report and decided to close since being out of scope for the Horizon bug bounty program."</em></p><p><em>"claimed impact by the whitehat is not in scope for the bug bounty program"</em></p></blockquote><p>I read it again. And again.</p><p>Out of scope.</p><p>The asset — the Rust execution client — was in scope. They confirmed that in the same message. The severity — Critical — was in scope. They confirmed that too. The only thing "out of scope" was the <strong>impact</strong>.</p><p>What impact? Canonical fee-accounting validity failure. The verifier accepting fabricated refunds. The consensus-critical path trusting unverified payload data. The thing I'd spent fourteen sections documenting and six PoCs proving.</p><p>That impact was out of scope.</p><p>I looked at the timestamps.</p><p>4:15 AM — submitted. 4:22 AM — "being reviewed." 4:32 AM — closed.</p><p><strong>Seventeen minutes.</strong></p><hr><h3 id="h-the-math" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The math</h3><p>Let me put seventeen minutes in context.</p><p>My report was approximately 12,000 words. The average reading speed for technical English is about 200 words per minute. So reading the report alone — just reading, not analyzing, not running code, not checking the math — would take sixty minutes.</p><p>It was closed in seventeen.</p><p>That means one of two things. Either the reviewer read approximately 3,400 of the 12,000 words before deciding — which means they stopped before reaching Section 3 (Root Cause), let alone the PoCs, the patches, the economic model, or the conservation proof.</p><p>Or they didn't read it at all.</p><p>I don't know which is worse.</p><hr><h3 id="h-how-to-improve" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">"How to improve"</h3><p>Below the closure message, there was a section labeled "How to improve." Helpful advice for next time, generated by the platform.</p><p>I want to share some of that advice. Because I think it's important that you see it.</p><blockquote><p><em>"Provide a Clear PoC: Include a working proof of concept that reproduces the issue and demonstrates the claimed impact."</em></p></blockquote><p>I had six.</p><blockquote><p><em>"Add Sufficient Detail: Give step-by-step reproduction instructions on top of a runnable PoC."</em></p></blockquote><p>I had <code>cargo test</code> commands with exact test names, commit hashes, and expected output for every single PoC.</p><blockquote><p><em>"Reference specific code snippets or modules."</em></p></blockquote><p>I had file:line references for every claim. <code>mod.rs:534-567</code>. <code>inspector.rs:ensure_top_level_initialized</code>. <code>core.rs:310</code>. Verbatim source in Appendix A.</p><blockquote><p><em>"Explain the vulnerability's context and impact precisely."</em></p></blockquote><p>I had an economic model with per-transaction USD calculations at four gas price tiers, extrapolated to 30-day and annual exposure, broken down by honest-path and verification-gap scenarios. With Python-verified arithmetic.</p><p>The "How to improve" advice was telling me to do everything I had already done.</p><p>It was a template. A form letter pasted under a seventeen-minute verdict. The same advice that goes under every closure, whether the report is a three-sentence copy-paste or a fourteen-section technical analysis with six executable proofs.</p><p>The guillotine doesn't look at what's under it. It just falls.</p><hr><h3 id="h-what-i-didnt-know" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">What I didn't know</h3><p>After the blade came down, I sat there for a while. Melon soda going flat. Terminal still open. The report still on my screen — all fourteen sections, all six PoCs, all those days.</p><p>I felt what every freelancer feels when their work gets rejected without being read. Not anger, exactly. More like — nothing. Acceptance.</p><p>I've been an audio engineer for thirty-one years. Thirty-one years of reading waveforms, tracing signal chains, calibrating outputs. In that world, I know every rule, every trick, every shortcut. I know when someone's bullshitting me and when they're not.</p><p>In this world, I was on day one.</p><p>Seventeen minutes? Maybe that's normal. "Out of scope"? Maybe I got the category wrong. "How to improve: add a PoC"? Maybe my six PoCs weren't in the right format. The closure template told me what I should have done, and I had no way to know whether the template was honest or automated.</p><p>So I thought: that's how it works here.</p><p>I didn't feel robbed. I didn't feel cheated. I didn't suspect the verdict was forged. I just thought I'd made a first-timer's mistake, and I'd do better next time.</p><p>A thirty-one-year professional, classified as "low-level" by a system he'd walked into yesterday, paying $50 to submit work that gets closed in seventeen minutes. And thinking: that's how it works.</p><p>That's the most honest thing I can tell you about that night. Not rage. Not conspiracy theories. Just a guy sitting alone at 4:33 AM with a flat melon soda, thinking he'd done something wrong.</p><p>So I did what you do. I accepted it. I figured I'd learn the rules, do better next time. $50 a ticket. I could afford a few more tries.</p><p>I didn't know that the thing I was holding — the finding the guillotine stamped "out of scope" in seventeen minutes — sat in the severity tier that pays up to $2,000,000.</p><p>A low-level researcher. $50 a ticket. Holding a $2,000,000 finding. And he didn't even know it.</p><hr><h3 id="h-can-you-believe-this" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Can you believe this?</h3><p>I want to step out of the story for a second and talk to you directly.</p><p>Does this happen in any other profession?</p><p>If a structural engineer submits a report saying a bridge has a crack in a load-bearing beam — does the city close the report in seventeen minutes and tell them "please include more detail"? When the report already has stress calculations, photographs, material analysis, and a repair plan?</p><p>If an auditor at a bank finds a discrepancy in the books — does the bank charge the auditor $50 for the privilege of reporting it, stamp "out of scope" on the cover page, and send back a template saying "please reference specific accounts"? When the report already lists every account number, every transaction, and every line in the ledger?</p><p>If a doctor tells a hospital "this patient's left and right readings don't match, here are the test results" — does the hospital close the case in seventeen minutes and say "please provide test results"?</p><p>No. In every other field, when a professional presents evidence, someone reads it. Maybe they disagree. Maybe the evidence is wrong. But someone <em>reads it</em>.</p><p>I submitted six executable proofs, fourteen sections of analysis, two patch layers with test results, and terminal logs with commit hashes. The platform took $100, closed the report in seventeen minutes, and told me to include a PoC.</p><p>I'm not asking you to feel sorry for me. I'm asking you to notice that this is not normal. In no industry, in no profession, in no system that calls itself legitimate, does this happen.</p><p>And yet here we are. And yet I paid $50 and submitted again.</p><hr><h3 id="h-the-scoreboard" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The scoreboard</h3><p>Here's what the scoreboard looked like after that night.</p><table><colgroup><col><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><div data-type="x402Embed"></div></th><th colspan="1" rowspan="1"><p>Ishijima</p></th><th colspan="1" rowspan="1"><p>Gatekeeper</p></th></tr><tr><td colspan="1" rowspan="1"><p>Time invested</p></td><td colspan="1" rowspan="1"><p>Days</p></td><td colspan="1" rowspan="1"><p>17 minutes</p></td></tr><tr><td colspan="1" rowspan="1"><p>Money spent</p></td><td colspan="1" rowspan="1"><p>$100 (report 1 of 7)</p></td><td colspan="1" rowspan="1"><p>$0</p></td></tr><tr><td colspan="1" rowspan="1"><p>Total by the end</p></td><td colspan="1" rowspan="1"><p>$100 + $50 × 6 = $400</p></td><td colspan="1" rowspan="1"><p>$0</p></td></tr><tr><td colspan="1" rowspan="1"><p>Sections written</p></td><td colspan="1" rowspan="1"><p>14</p></td><td colspan="1" rowspan="1"><p>1 (template)</p></td></tr><tr><td colspan="1" rowspan="1"><p>PoCs attached</p></td><td colspan="1" rowspan="1"><p>6</p></td><td colspan="1" rowspan="1"><p>0 read</p></td></tr><tr><td colspan="1" rowspan="1"><p>Code lines cited</p></td><td colspan="1" rowspan="1"><p>47</p></td><td colspan="1" rowspan="1"><p>0</p></td></tr><tr><td colspan="1" rowspan="1"><p>Deposit returned</p></td><td colspan="1" rowspan="1"><p>No</p></td><td colspan="1" rowspan="1"><p>—</p></td></tr><tr><td colspan="1" rowspan="1"><p>Verdict</p></td><td colspan="1" rowspan="1"><p>—</p></td><td colspan="1" rowspan="1"><p>CLOSED</p></td></tr></tbody></table><p>Seven reports. Seven deposits. Not one returned. Not one read past the first scroll.</p><p>But that's the final scoreboard. This was still round one.</p><p>I stared at the scoreboard for a long time.</p><p>Then I opened a new file.</p><p>If seventeen minutes is all they give you, then the next report has to be a weapon that works in seventeen minutes. Not a fourteen-section treatise. A blade. Something where Section 1 is already the killing blow, and everything after is insurance.</p><p>The gatekeeper swings the guillotine. The researcher sharpens the sword.</p><hr><h3 id="h-payload" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">payload</h3><p>I want to tell you something about the word "payload."</p><p>In Episode 1, I told you it means "the data blob the sequencer packs into a block." That's the technical definition. But the word has another meaning — an older one.</p><p>In rocketry, the payload is the warhead. The thing the missile carries. The delivery vehicle doesn't matter. The fuel doesn't matter. The trajectory doesn't matter. The only thing that matters is whether the payload reaches the target.</p><p>My report was the delivery vehicle. Fourteen sections of fuel, six PoCs of trajectory.</p><p>The payload — the core finding, the thing that matters — is one sentence:</p><p><strong>The consensus-critical Verify path accepts producer-asserted refund values without independent recomputation.</strong></p><p>That sentence is still true. The guillotine didn't change the code. The closure didn't fix the bug. The seventeen minutes didn't make the PoCs fail.</p><p>The payload is still live.</p><hr><blockquote><p><strong>$50 to submit. $2,000,000 on the table. Seventeen minutes to close. And the researcher thought he'd done something wrong.</strong></p></blockquote><hr><p><em>Episode 4: "Friendly Fire" — coming next.</em></p><hr><p><strong>Glossary</strong> (new terms this episode)</p><table><colgroup><col><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>In the Story</p></th><th colspan="1" rowspan="1"><p>In the Code</p></th><th colspan="1" rowspan="1"><p>What It Actually Means</p></th></tr><tr><td colspan="1" rowspan="1"><p>The guillotine</p></td><td colspan="1" rowspan="1"><p>Triage closure</p></td><td colspan="1" rowspan="1"><p>A report killed faster than it can be read</p></td></tr><tr><td colspan="1" rowspan="1"><p>Seventeen minutes</p></td><td colspan="1" rowspan="1"><p>4:15 AM → 4:32 AM</p></td><td colspan="1" rowspan="1"><p>The time between submission and death</p></td></tr><tr><td colspan="1" rowspan="1"><p>The template</p></td><td colspan="1" rowspan="1"><p>"How to improve"</p></td><td colspan="1" rowspan="1"><p>Generic advice pasted under every closure</p></td></tr><tr><td colspan="1" rowspan="1"><p>The scoreboard</p></td><td colspan="1" rowspan="1"><p>—</p></td><td colspan="1" rowspan="1"><p>Days of work vs. 17 minutes of review</p></td></tr><tr><td colspan="1" rowspan="1"><p>The payload (warhead)</p></td><td colspan="1" rowspan="1"><p>Core finding</p></td><td colspan="1" rowspan="1"><p>The one sentence that survives everything</p></td></tr><tr><td colspan="1" rowspan="1"><p>CLOSED</p></td><td colspan="1" rowspan="1"><p>Report status</p></td><td colspan="1" rowspan="1"><p>The only word that matters to the platform</p></td></tr></tbody></table><hr><p><em>Everything is Speculation — YomibitoShirazu</em> <span data-name="copyright" class="emoji" data-type="emoji">©</span><em> 2025 algorithm.dance</em></p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/05bbfc8a6be3ab067425b491a0e8953993b4d85d7347b0a912be8a20cad948eb.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Episode 2: The Second Piton]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/episode-2-the-second-piton</link>
            <guid>YpdG3c7VS9poKE5NAZnO</guid>
            <pubDate>Tue, 14 Jul 2026 17:47:48 GMT</pubDate>
            <description><![CDATA[All characters are anonymous. All events are speculation. You're reading the war room notes of a masked security researcher. Don't ask how I got these. The forge A proof of concept isn't an opinion. It's a machine. You feed it inputs. It produces outputs. If the outputs match your hypothesis, you have evidence. If they don't, you were wrong. Either way, the machine doesn't care. The machine doesn't argue. The machine just runs. That's why I like PoCs more than I like people. After finding the...]]></description>
            <content:encoded><![CDATA[<blockquote><p><em>All characters are anonymous. All events are speculation.</em></p><p><em>You're reading the war room notes of a masked security researcher.</em></p><p><em>Don't ask how I got these.</em></p></blockquote><hr><h3 id="h-the-forge" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The forge</h3><p>A proof of concept isn't an opinion.</p><p>It's a machine.</p><p>You feed it inputs. It produces outputs.</p><p>If the outputs match your hypothesis, you have evidence. If they don't, you were wrong.</p><p>Either way, the machine doesn't care. The machine doesn't argue. The machine just runs.</p><p>That's why I like PoCs more than I like people.</p><p>After finding the asymmetry between the Go and Rust verifiers — one audits, the other nods — I had a hypothesis.</p><p>Now I needed a machine.</p><p>Actually, I needed two.</p><hr><h3 id="h-e1-the-inflated-refund" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">E1: The inflated refund</h3><p>The first PoC was straightforward.</p><p>I needed to prove that the Rust verifier accepts an inflated refund without catching it.</p><p>Here's the setup.</p><p>Take two transactions in the same block.</p><p>The first transaction touches some accounts — warms them up, in EVM terminology.</p><p>The second transaction touches the same accounts.</p><p>Under SDM (Sequencer-Defined Metering), the second transaction should get a refund for those pre-warmed accounts, because it didn't have to pay the cold-access surcharge a second time.</p><p>Fair enough. That's the whole point of SDM.</p><p>But here's the thing.</p><p>The honest refund for that second transaction — when you actually calculate it from first principles — is <strong>10,000 gas</strong>.</p><p>Five accounts, 2,500 gas each.</p><p>Caller, target, and three fee recipients (L1, base fee, operator).</p><p>They were all warmed by the first transaction, so the second transaction gets credited for not paying cold-access on them.</p><p>10,000 gas. That's the real number.</p><p>Now.</p><p>What if the sequencer writes <strong>21,000</strong> instead?</p><p>The Go verifier would catch it. It recalculates independently, gets 10,000, compares to the sequencer's 21,000, and rejects. Done.</p><p>The Rust verifier?</p><p>It checks: is 21,000 less than or equal to <code>evm_gas_used</code>?</p><p>If the transaction used 21,000 gas — yes.</p><p><strong>Accepted.</strong></p><p>11,000 gas of pure inflation, waved through without a second glance.</p><p>I wrote the test. I named it <code>phantom_refund_measure</code>.</p><p>I ran it against the real <code>alloy-op-evm</code> crate, not a mock — the actual production code at commit <code>4c8b174</code>.</p><pre data-type="codeBlock" text="baseline (exclude none)          | tx0=     0 | tx1= 12500
exclude caller                   | tx0=     0 | tx1= 10000   (-2500)
exclude target                   | tx0=     0 | tx1= 10000   (-2500)
exclude L1_FEE_RECIPIENT         | tx0=     0 | tx1= 10000   (-2500)
exclude BASE_FEE_RECIPIENT       | tx0=     0 | tx1= 10000   (-2500)
exclude OPERATOR_FEE_RECIPIENT   | tx0=     0 | tx1= 10000   (-2500)
"><code>baseline (exclude none)          <span class="hljs-operator">|</span> tx0<span class="hljs-operator">=</span>     <span class="hljs-number">0</span> <span class="hljs-operator">|</span> tx1<span class="hljs-operator">=</span> <span class="hljs-number">12500</span>
exclude caller                   <span class="hljs-operator">|</span> tx0<span class="hljs-operator">=</span>     <span class="hljs-number">0</span> <span class="hljs-operator">|</span> tx1<span class="hljs-operator">=</span> <span class="hljs-number">10000</span>   (<span class="hljs-number">-2500</span>)
exclude target                   <span class="hljs-operator">|</span> tx0<span class="hljs-operator">=</span>     <span class="hljs-number">0</span> <span class="hljs-operator">|</span> tx1<span class="hljs-operator">=</span> <span class="hljs-number">10000</span>   (<span class="hljs-number">-2500</span>)
exclude L1_FEE_RECIPIENT         <span class="hljs-operator">|</span> tx0<span class="hljs-operator">=</span>     <span class="hljs-number">0</span> <span class="hljs-operator">|</span> tx1<span class="hljs-operator">=</span> <span class="hljs-number">10000</span>   (<span class="hljs-number">-2500</span>)
exclude BASE_FEE_RECIPIENT       <span class="hljs-operator">|</span> tx0<span class="hljs-operator">=</span>     <span class="hljs-number">0</span> <span class="hljs-operator">|</span> tx1<span class="hljs-operator">=</span> <span class="hljs-number">10000</span>   (<span class="hljs-number">-2500</span>)
exclude OPERATOR_FEE_RECIPIENT   <span class="hljs-operator">|</span> tx0<span class="hljs-operator">=</span>     <span class="hljs-number">0</span> <span class="hljs-operator">|</span> tx1<span class="hljs-operator">=</span> <span class="hljs-number">10000</span>   (<span class="hljs-number">-2500</span>)
</code></pre><p>Each of those five accounts contributes exactly 2,500 gas of phantom refund.</p><p>Remove one, and the refund drops by exactly 2,500.</p><p>Deterministic. Reproducible. No randomness, no edge cases, no "it depends."</p><p>But that was just the honest path — what the sequencer <em>actually</em> computes when it's not lying.</p><p>The more important question was:</p><p>What does the verifier accept when the sequencer <em>is</em> lying?</p><hr><h3 id="h-the-honest-path-is-already-broken" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The honest path is already broken</h3><p>Before I even got to the forgery test, I realized something unsettling.</p><p>The honest path — the one where nobody is lying, nobody is compromised, just normal operation — was already producing phantom refunds.</p><p>Let me explain.</p><p>Under SDM, a refund is supposed to compensate a transaction for cold-access costs it didn't actually incur, because a previous transaction in the same block already warmed those accounts.</p><p>The key word is "actually incur."</p><p>You should only get a refund if you <em>would have</em> paid the cold surcharge but didn't, because someone else already did.</p><p>But the <code>caller</code> and <code>target</code> of a transaction are <em>always</em> warm at the start of that transaction — that's how the EVM works (EIP-2929).</p><p>They never pay the cold surcharge in the first place.</p><p>So a refund for them makes no sense.</p><p>You can't get money back for something you never paid.</p><p>Same for the three fee recipients.</p><p>They're not touched by the transaction's EVM execution. They're touched by the protocol — the settlement layer that distributes fees after execution.</p><p>The transaction never paid cold access for them, either.</p><p>And yet.</p><p>The SDM inspector was marking all five as refund-eligible.</p><p>Every non-first, non-deposit transaction in every block was getting 7,500 to 12,500 gas of free refund.</p><p>On autopilot.</p><p>I wrote four more tests to map it out.</p><p><code>phantom_refund_unrelated</code>: Two completely unrelated senders and targets. Second transaction still gets 7,500 gas of phantom refund. The three fee vaults alone are enough — they're shared across every transaction in the block.</p><p><code>phantom_refund_pingpong</code>: 100 accounts, 12 transactions, rotating senders and targets. Every transaction after the first gets 10,000 gas of phantom refund. The cap (<code>refund &lt;= evm_gas_used</code>) is never violated.</p><p><code>phantom_refund_inflate</code>: A contract that SLOADs 60 storage slots. The refund stays constant at 12,500 regardless of how many real cold accesses occur. The phantom is fixed at five accounts — it doesn't inflate with real work, but it doesn't go away either.</p><p><code>phantom_refund_supply</code>: Total ETH before and after the block. Equal. Not a mint — a conserved transfer. The sender gains exactly what the fee recipients lose. No new money is created. But the accounting is wrong.</p><p>Five tests. Five files. All green.</p><p>The phantom is real, deterministic, and affects essentially every transaction after the first in every block.</p><p>But this was E1. The first piton.</p><p>The one that says "the auditor is sloppy."</p><p>I needed the second one — the one that says "the auditor is blind."</p><hr><h3 id="h-rung1-zero-to-21000" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">rung1: Zero to 21,000</h3><p>This is the test that matters.</p><p>Not "the refund is inflated by 11,000." Not "the honest path has a phantom."</p><p>Those are important, but a triage team can wave them away.</p><p>"It's a known limitation." "The spec allows flexibility." "The delta is within operational tolerance."</p><p>rung1 can't be waved away.</p><p>Here's the setup:</p><p>First transaction in a block. Nothing has been warmed. No previous transactions have touched any accounts.</p><p>The honest SDM refund for this transaction is exactly <strong>zero</strong>.</p><p>Not 10,000. Not 7,500. Zero.</p><p>Because there's no previous transaction to have warmed anything.</p><p>Now the sequencer packs the payload with:</p><pre data-type="codeBlock" text="SDMGasEntry { index: 0, gas_refund: 21_000 }
"><code><span class="hljs-string">SDMGasEntry</span> { <span class="hljs-attr">index:</span> <span class="hljs-number">0</span>, <span class="hljs-attr">gas_refund:</span> <span class="hljs-string">21_000</span> }
</code></pre><p>Index 0 — the first transaction.</p><p>Refund: 21,000 gas — the full gas limit of a basic transfer.</p><p>On a transaction where the legitimate refund is zero.</p><p>I set the executor to <code>PostExecMode::Verify</code> — the mode that replicas and fault-proof executors use.</p><p>Not the producer mode. The verification mode. The one that's supposed to catch lies.</p><p>I ran the test.</p><pre data-type="codeBlock" text="honest SDM refund for first tx = 0
verifier-applied canonical_gas_used = 0
"><code>honest SDM refund for first <span class="hljs-attr">tx</span> = <span class="hljs-number">0</span>
verifier-applied <span class="hljs-attr">canonical_gas_used</span> = <span class="hljs-number">0</span>
</code></pre><p>canonical_gas_used = 0.</p><p>The verifier subtracted the full 21,000 from the gas used.</p><p>On a first transaction with zero warming.</p><p>The canonical gas accounting now says this transaction used zero gas.</p><p>And the verifier said: <strong>accepted.</strong></p><p>No recalculation. No comparison. No "wait, the honest refund should be zero, but the sequencer claimed 21,000."</p><p>Just a bounds check — is 21,000 ≤ 21,000? Yes. Pass.</p><p>The auditor didn't just miss a discrepancy.</p><p>The auditor accepted a fabrication from nothing.</p><p>From zero, to 21,000.</p><p>The entire gas cost of a transaction, erased by a single number in a payload that nobody verified.</p><hr><h3 id="h-what-the-numbers-mean" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">What the numbers mean</h3><p>Let me translate this out of gas units and into money.</p><p>When the verifier accepts a forged refund of V gas, the settlement function (<code>apply_post_exec_refund_to_state</code>) does this:</p><pre data-type="codeBlock" text="sender_balance += V * effective_gas_price
beneficiary_balance -= portion
base_fee_balance -= portion  
operator_fee_balance -= portion
"><code>sender_balance <span class="hljs-operator">+</span><span class="hljs-operator">=</span> V <span class="hljs-operator">*</span> effective_gas_price
beneficiary_balance <span class="hljs-operator">-</span><span class="hljs-operator">=</span> portion
base_fee_balance <span class="hljs-operator">-</span><span class="hljs-operator">=</span> portion  
operator_fee_balance <span class="hljs-operator">-</span><span class="hljs-operator">=</span> portion
</code></pre><p>The sender — which could be the attacker — gets credited. The fee recipients get debited.</p><p>Conserved. No mint. But money moves.</p><p>V is attacker-controlled.</p><p>The ceiling is <code>evm_gas_used</code> — for a complex transaction touching many contracts, that could be millions of gas.</p><p>Multiply by the gas price, and you have real ETH.</p><p>And this happens in the consensus-critical Verify path.</p><p>The same path used by <code>x-reth</code>, <code>nova</code>, and every fault-proof executor.</p><p>The path that determines what the canonical chain state actually is.</p><p>Whatever the sequencer writes in the payload becomes truth.</p><p>Not because anyone checked it.</p><p>Because nobody did.</p><hr><h3 id="h-two-pitons-set" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Two pitons, set</h3><p>I organized the tests into two folders.</p><p><strong>PoC A</strong> — honest path phantom (five test files):</p><ul><li><p><code>phantom_refund_measure.rs</code> — per-account contribution, 2,500 each</p></li><li><p><code>phantom_refund_unrelated.rs</code> — unrelated senders still refunded (7,500 floor)</p></li><li><p><code>phantom_refund_pingpong.rs</code> — 100 accounts, cap never violated</p></li><li><p><code>phantom_refund_inflate.rs</code> — phantom fixed at 5 accounts, independent of real work</p></li><li><p><code>phantom_refund_supply.rs</code> — total supply conserved (no mint)</p></li></ul><p><strong>PoC B</strong> — verifier validity failure (one test file):</p><ul><li><p><code>verifier_unchecked_refund.rs</code> — first tx, honest=0, forged=21,000, accepted</p></li></ul><p>Six files. All running against the real production code. All reproducible with <code>cargo test</code>. Every number captured in terminal logs with the commit hash.</p><p>PoC A shows that the system is broken even without malice. PoC B shows that a malicious sequencer can exploit the break.</p><p>Together:</p><p>The honest path produces phantom refunds, and the verification path accepts fabricated ones without checking.</p><p>Two pitons. Both in the rock.</p><hr><h3 id="h-the-layer-problem" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The layer problem</h3><p>There was one more thing I had to prove before writing the report.</p><p>If you fix the producer — the SDM inspector that grants the phantom refunds — does that fix the verifier too?</p><p>No.</p><p>I wrote a patch for the inspector.</p><p>Made caller, target, and fee-vault touches refund-ineligible.</p><p>Ran PoC A.</p><p>All phantom refunds dropped to zero. Fixed.</p><p>Then I ran PoC B — the verifier test — with only the producer patch applied.</p><pre data-type="codeBlock" text="honest SDM refund for first tx = 0
verifier-applied canonical_gas_used = 0      # unchanged
"><code>honest SDM refund for first <span class="hljs-attr">tx</span> = <span class="hljs-number">0</span>
verifier-applied <span class="hljs-attr">canonical_gas_used</span> = <span class="hljs-number">0</span>      <span class="hljs-comment"># unchanged</span>
</code></pre><p>Still accepted.</p><p>The producer-only fix changes what the honest sequencer <em>would</em> compute, but it doesn't change what the verifier <em>accepts</em>.</p><p>The Verify path still takes the payload at face value.</p><p>You can fix the kitchen, but if the accountant doesn't audit the receipts, a forged receipt still goes through.</p><p>So I wrote a second patch.</p><p>This one on the Verify path itself.</p><p>Made the verifier re-run the SDM inspector and compare the result to the sequencer's claim:</p><pre data-type="codeBlock" text="if claimed != recomputed {
    return Err(&quot;payload refund does not match recomputed legitimate refund&quot;)
}
"><code><span class="hljs-keyword">if</span> claimed <span class="hljs-operator">!</span><span class="hljs-operator">=</span> recomputed {
    <span class="hljs-keyword">return</span> Err(<span class="hljs-string">"payload refund does not match recomputed legitimate refund"</span>)
}
</code></pre><p>Ran PoC B again.</p><pre data-type="codeBlock" text="thread '...' panicked:
payload refund 21000 does not match recomputed legitimate refund 0 for tx index 0
"><code>thread <span class="hljs-string">'...'</span> panicked:
payload refund <span class="hljs-number">21000</span> does <span class="hljs-keyword">not</span> match recomputed legitimate refund <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> tx index <span class="hljs-number">0</span>
</code></pre><p><strong>Rejected.</strong></p><p>The fix needs two layers.</p><p>Layer 1 (producer) closes the honest-path phantom. Layer 2 (verifier) closes the forgery path.</p><p>Layer 1 alone is insufficient — it leaves PoC B passing.</p><p>Both are required.</p><p>I documented this in the report.</p><p>The fix direction, the test results, and the explicit statement:</p><p>"A fix that only changes SDMWarmingInspector / Produce mode is insufficient."</p><hr><h3 id="h-before-the-wall" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Before the wall</h3><p>Everything was ready.</p><p>Six PoC files. Two patch layers. Terminal logs with commit hashes.</p><p>A complete write-up: root cause, affected components, data flow diagram, severity analysis, economic model, conservation proof, fix direction, test results.</p><p>Fourteen sections. Appendices A through D.</p><p>Every claim backed by executed code, not speculation.</p><p>I looked at the clock. It was 4 AM.</p><p>The same hour I'd be clicking "Submit" when the time came.</p><p>Two pitons in the rock. A rope clipped to each. Enough gear for the ascent.</p><p>But above me — I could feel it — the wall was waiting.</p><p>Somewhere up there in the fog, the gatekeeper sat behind a desk with a single stamp.</p><p><strong>CLOSED.</strong></p><p>I didn't know yet how fast that stamp would come down.</p><p>I didn't know it would take less time to close my report than it takes to read this paragraph.</p><p>But I knew the pitons were real. The code was real. The numbers were real.</p><p>And I knew that whatever happened next, the machine wouldn't lie.</p><p>The machine doesn't argue. The machine just runs.</p><hr><blockquote><p><strong>Two pitons. Now climb.</strong></p></blockquote><hr><p><em>Episode 3: "The Guillotine" — coming next.</em></p><hr><p><strong>Glossary</strong> (new terms this episode)</p><table><colgroup><col><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>In the Story</p></th><th colspan="1" rowspan="1"><p>In the Code</p></th><th colspan="1" rowspan="1"><p>What It Actually Means</p></th></tr><tr><td colspan="1" rowspan="1"><p>E1 / first piton</p></td><td colspan="1" rowspan="1"><p>PoC A (phantom_refund_*.rs)</p></td><td colspan="1" rowspan="1"><p>Tests proving honest path grants phantom refunds</p></td></tr><tr><td colspan="1" rowspan="1"><p>rung1 / second piton</p></td><td colspan="1" rowspan="1"><p>PoC B (verifier_unchecked_refund.rs)</p></td><td colspan="1" rowspan="1"><p>Test proving verifier accepts fabricated refund (0→21,000)</p></td></tr><tr><td colspan="1" rowspan="1"><p>Phantom refund</p></td><td colspan="1" rowspan="1"><p>SDM refund for non-cold accounts</p></td><td colspan="1" rowspan="1"><p>Refund granted when no cold surcharge was paid</p></td></tr><tr><td colspan="1" rowspan="1"><p>canonical_gas_used</p></td><td colspan="1" rowspan="1"><p>evm_gas_used - refund</p></td><td colspan="1" rowspan="1"><p>The "official" gas used, after the unverified refund</p></td></tr><tr><td colspan="1" rowspan="1"><p>Layer 1 fix</p></td><td colspan="1" rowspan="1"><p>Producer/inspector patch</p></td><td colspan="1" rowspan="1"><p>Fixes what the honest sequencer computes</p></td></tr><tr><td colspan="1" rowspan="1"><p>Layer 2 fix</p></td><td colspan="1" rowspan="1"><p>Verifier/consensus patch</p></td><td colspan="1" rowspan="1"><p>Fixes what the verifier accepts — the one that matters</p></td></tr><tr><td colspan="1" rowspan="1"><p>4c8b174</p></td><td colspan="1" rowspan="1"><p>Git commit hash</p></td><td colspan="1" rowspan="1"><p>The exact code version all tests ran against</p></td></tr></tbody></table><hr><p><em>Everything is Speculation — YomibitoShirazu</em><span data-name="copyright" class="emoji" data-type="emoji">©</span><em> 2025 algorithm.dance</em></p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <category>btc</category>
            <category>eth</category>
            <category>web3</category>
            <category>dev</category>
            <category>security</category>
            <category>cybersecurity</category>
            <category>bugbounty</category>
            <category>exploit</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/dd244d399183003796996c8dc41918d244bc2d115739b85cb46aadfe352d4eeb.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Everything is Speculation]]></title>
            <link>https://paragraph.com/@yomibitoshirazu/everything-is-speculation</link>
            <guid>V856zxroxJznTtifc7U0</guid>
            <pubDate>Tue, 14 Jul 2026 11:08:12 GMT</pubDate>
            <description><![CDATA[All characters are anonymous. All events are speculation. You're reading the war room notes of a masked security researcher. Don't ask how I got these. How I got here I'm not a security researcher. Or I wasn't, anyway. I'm an audio engineer. A music producer, to be specific — the kind who spends hours adjusting the balance between the left and right channels of a stereo mix, chasing a phantom 0.5 dB imbalance that nobody else can hear. That's what I do. That's what I'm trained for. Listening ...]]></description>
            <content:encoded><![CDATA[<div data-type="x402Embed"></div><blockquote><p><em>All characters are anonymous. All events are speculation.</em></p><p><em>You're reading the war room notes of a masked security researcher.</em></p><p><em>Don't ask how I got these.</em></p></blockquote><hr><h3 id="h-how-i-got-here" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">How I got here</h3><p>I'm not a security researcher.</p><p>Or I wasn't, anyway.</p><p>I'm an audio engineer.</p><p>A music producer, to be specific — the kind who spends hours adjusting the balance between the left and right channels of a stereo mix, chasing a phantom 0.5 dB imbalance that nobody else can hear.</p><p>That's what I do. That's what I'm trained for.</p><p>Listening to two things that are supposed to be identical and catching the moment they're not.</p><p>I've been doing this since I was fourteen — </p><p>since a Mac I inherited from my mother, </p><p>who didn't make it to see me use it.</p><p>That was thirty-one years ago.</p><br><p>The audio business wasn't exactly booming. I was — to put it politely — between gigs. A lot of between gigs.</p><p>Enough between gigs that I started clicking on articles I would normally ignore.</p><p>One of them had a headline about a <strong>$2 million bug bounty payout</strong>.</p><p>Some hacker found a vulnerability in a blockchain protocol and got paid seven figures for reporting it.</p><p>$2 million. For finding a bug.</p><p>I didn't know what a "Layer 2" was. I didn't know what a "sequencer" did. I didn't know Rust from Go.</p><p>But I knew how to read documentation. I knew how to trace signal flow.</p><p>And I knew — very well — what it sounds like when the left channel and the right channel don't match.</p><p>That's how I ended up here.</p><hr><p>My name is Ishijima.</p><p>Online, I go by <strong>YomibitoShirazu</strong> — a Japanese literary term meaning "author unknown."</p><p>In classical poetry anthologies, it's the attribution given when the poet's name has been lost to history.</p><p>Nobody knows who wrote it, but the poem remains.</p><p>Felt appropriate for a guy who wandered into someone else's field and found something he wasn't supposed to find.</p><p>One thing I realized on day one:</p><p>This work is extreme climbing.</p><p>You're alone on a wall of code, thousands of lines high, testing each hold one by one.</p><p>Most of the rock is solid.</p><p>Then your fingers close around something and it moves.</p><p>That's the moment. That's why you climb.</p><p>I grabbed a melon soda and started reading.</p><hr><h3 id="h-the-beginning" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The beginning</h3><p>Spring 2025. I was auditing a Layer 2 blockchain I'll call <strong>Horizon</strong>.</p><p>If you're reading this on Paragraph, you probably know what a Layer 2 is.</p><p>But just in case — or in case you want to forward this to your non-crypto friend who keeps asking what you do for a living — here's the short version.</p><p>A blockchain is a ledger.</p><p>That's it.</p><p>A giant, shared, append-only ledger.</p><p>"A sent 100 to B." "C's balance is now 200."</p><p>Every transaction, every balance change, written down permanently.</p><p>The whole point is that <em>anyone</em> can verify the math.</p><p>You don't need to trust a bank. You don't need to trust a government. You just need to trust arithmetic.</p><p>Now, doing all that arithmetic directly on Ethereum (Layer 1) is expensive.</p><p>So Layer 2s exist.</p><p>They do the heavy computation off-chain, then post a compressed summary back to Ethereum.</p><p>Faster. Cheaper. Same security guarantees.</p><p>At least, that's the promise.</p><hr><p>The way it works:</p><p>A <strong>sequencer</strong> collects transactions and executes them. Think of the sequencer as a bank teller who processes your deposit.</p><p>Then, separately, a <strong>verifier</strong> takes the same transactions and re-executes them from scratch.</p><p>If the verifier gets the same result as the sequencer — great. Everything checks out.</p><p>If the results don't match — the verifier can prove the sequencer lied. This is called a <strong>Fault Proof</strong>.</p><p>This is the core security model. The entire reason people trust L2s with billions of dollars:</p><p><strong>You don't have to trust the teller. Because anyone can audit the books.</strong></p><p>Remember that sentence. It's going to matter.</p><hr><h3 id="h-two-auditors" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Two auditors</h3><p>So there I was, reading the verifier code. The part that audits the sequencer.</p><p>Horizon had two implementations of the verifier. One written in Go. One in Rust.</p><p>This is actually good engineering.</p><p>If you have two independent implementations of the same logic, written in different languages by different teams, and they both produce the same result — you can be pretty confident the result is correct.</p><p>It's the same reason airplanes have redundant systems. One engine fails, the other keeps you in the air.</p><p>Two auditors checking the same books. Belt and suspenders.</p><p>I started with Go.</p><p>Opened the file. Found the verification function.</p><p>And right there, clear as day:</p><pre data-type="codeBlock" text="if replay.Summary.ReplayRefundTotal != replay.Summary.PayloadRefundTotal {
    return nil, fmt.Errorf(...)
}
"><code><span class="hljs-keyword">if</span> replay.Summary.ReplayRefundTotal <span class="hljs-operator">!</span><span class="hljs-operator">=</span> replay.Summary.PayloadRefundTotal {
    <span class="hljs-keyword">return</span> nil, fmt.Errorf(...)
}
</code></pre><p>Let me translate this for the non-Go speakers.</p><p><code>ReplayRefundTotal</code> — the refund value that the verifier calculated independently, by re-executing the transactions from scratch.</p><p><code>PayloadRefundTotal</code> — the refund value that the sequencer <em>claimed</em>.</p><p>The Go verifier compares these two numbers.</p><p>If they don't match? Error. Rejected.</p><p>Doesn't matter if the sequencer's number is higher, lower, or off by one wei. If it's not identical to the verifier's independent calculation, it's invalid.</p><p><strong>That's what auditing means.</strong></p><p>You don't take someone's word for it. You run the numbers yourself and check.</p><p>Good. Expected. Moving on.</p><hr><h3 id="h-wait" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Wait</h3><p>Then I opened the Rust verifier.</p><p>The equivalent function. The one that's supposed to do the same job.</p><pre data-type="codeBlock" text="fn verifier_post_exec_refund_for_tx(...) {
    // reject if refund &gt; evm_gas_used
    // ...that's it
}
"><code>fn <span class="hljs-title function_">verifier_post_exec_refund_for_tx</span>(<span class="hljs-params">...</span>) {
    <span class="hljs-comment">// reject if refund &gt; evm_gas_used</span>
    <span class="hljs-comment">// ...that's it</span>
}
</code></pre><p>I read it three times.</p><p>Here's the thing about being an audio engineer.</p><p>When you've spent years balancing stereo mixes, your brain develops a reflex.</p><p>You hear two channels that are supposed to be identical — left and right, both carrying the same signal — and the instant one of them is off, you know.</p><p>You don't need to run an analysis. You don't need to check the meters. Your ear tells you before your brain catches up.</p><p>Go: recalculate, compare, reject on mismatch.</p><p>Rust: check a ceiling, pass through.</p><p>Left channel: full signal. Right channel: limiter missing.</p><p>I didn't need to be a security expert to see this.</p><p>I needed to be someone trained to notice when two things that should be symmetric aren't.</p><p>And that's exactly what I am.</p><hr><p>There's no recalculation.</p><p>The Rust verifier doesn't independently compute what the refund <em>should</em> be.</p><p>It just looks at what the sequencer said the refund is, checks whether that number exceeds a ceiling (<code>evm_gas_used</code>), and if it doesn't — passes it through.</p><p>Let me make sure this is crystal clear, because everything that follows depends on it.</p><p><strong>Go verifier</strong>: "You say the refund is 21,000. Let me check. I calculated 10,000. Those numbers don't match. <strong>Rejected.</strong>"</p><p><strong>Rust verifier</strong>: "You say the refund is 21,000. The ceiling is 21,000. Looks fine. <strong>Accepted.</strong>"</p><p>The Go verifier does independent verification. The Rust verifier does a bounds check.</p><p>These are not the same thing.</p><p>A bounds check tells you the number isn't <em>impossibly</em> large. Independent verification tells you the number is <em>correct</em>.</p><p>The difference between "this isn't physically impossible" and "this is actually true."</p><p>Your credit card company checks whether a charge exceeds your limit.</p><p>That doesn't mean every charge below your limit is legitimate.</p><p>If someone steals your card and charges $99 on a $100 limit, the bounds check passes. But the charge is still fraud.</p><p>Same thing here.</p><p>The Rust verifier checks the ceiling. It doesn't check if the number is real.</p><hr><h3 id="h-why-this-matters" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Why this matters</h3><p>Maybe you're thinking:</p><p>"Okay, but this is a new feature, right? SDM — Sequencer-Defined Metering. Maybe the Rust behavior is intentional. Maybe the spec says the sequencer gets to pick whatever refund it wants."</p><p>Good question. I had the same one.</p><p>So I opened the spec.</p><p>SDM is a new mechanism in Horizon's upcoming upgrade.</p><p>It lets the sequencer define its own gas metering policy — specifically, how refunds are calculated when accounts that were already "warmed" in a previous transaction get accessed again.</p><p>The idea is efficiency:</p><p>If the sequencer already paid the cold-access cost for an account earlier in the block, a later transaction touching that same account shouldn't have to pay again.</p><p>Makes sense so far.</p><p>In the security considerations section of the SDM spec, there's this sentence:</p><blockquote><p><em>"the sequencer has complete freedom to allocate refunds according to arbitrary policy."</em></p></blockquote><p>And there it is. <strong>"Complete freedom."</strong></p><p>If you're the defense attorney for this code, that sentence is your entire case.</p><p>"Your Honor, my client — the Rust verifier — was simply following the spec. The spec says the sequencer has complete freedom. The verifier's job is to respect that freedom, not second-guess it."</p><p>If you're the prosecutor — if you're me — you read it very differently.</p><p>"Freedom" in a trustless system means the freedom to choose a <em>policy</em>.</p><p>Like choosing which compression algorithm to use for fee calculations.</p><p>It doesn't mean the freedom to fabricate numbers that nobody checks.</p><p>Think about it this way.</p><p>A restaurant menu says "tipping is at the customer's discretion."</p><p>That means you're free to tip 15% or 20% or nothing.</p><p>It doesn't mean you're free to write "-$50" on the tip line and take money out of the cash register.</p><p>"Discretion" implies a range of legitimate choices, not the absence of all rules.</p><p>But the Rust verifier has no way to distinguish between a legitimate policy choice and an outright fabrication.</p><p>Because it never recalculates.</p><hr><h3 id="h-the-question" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The question</h3><p>So here's where I sat for a while.</p><p>This is always the hardest part of the job.</p><p>Not finding the bug — that's just reading and pattern matching.</p><p>The hard part is the moment after, when you have to decide:</p><p>Is this really a bug? Or is this a design choice I just don't agree with?</p><p>Because if I report something that's genuinely by-design, I waste everyone's time, including mine. I look like an amateur. My reputation takes a hit.</p><p>But if I stay quiet about something that <em>is</em> a bug because I'm not sure — and that bug later gets exploited — that's worse.</p><p>The Go verifier checks. The Rust verifier doesn't. Both are supposed to implement the same security model.</p><p>One of them is wrong.</p><p>Either the Go verifier is being unnecessarily strict. Or the Rust verifier is missing a critical check.</p><p>Here's what made me lean toward the latter.</p><p>The Go code checks <code>ReplayRefundTotal != PayloadRefundTotal</code>.</p><p>That's not an accident.</p><p>Someone deliberately wrote that comparison.</p><p>Someone on the development team understood that the sequencer's claimed refund needs to be validated against an independent calculation.</p><p>The logic exists. In production code. Tested. Shipped.</p><p>It just... isn't in the Rust path.</p><p>And here's the kicker:</p><p>The Rust path is the one that matters for consensus.</p><p>It's the path used by <code>x-reth</code> and <code>nova</code> — the execution clients that actually determine what the canonical chain state is.</p><p>The Go path is an off-chain validator. Important, but not consensus-critical.</p><p>The check exists where it's optional. It's missing where it's mandatory.</p><hr><h3 id="h-the-gatekeeper" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The gatekeeper</h3><p>Once I decided this was real, the next question was: what happens when I report it?</p><p>I know the process.</p><p>You submit through a bounty platform — let's call it <strong>Sentinel</strong> — and your report goes to a triage team first.</p><p>The triage team decides whether it's valid, before the actual development team ever sees it.</p><p>Triage has absolute power.</p><p>They can close any report with a single comment:</p><p>"Out of scope." "By-design." "Does not demonstrate impact."</p><p>And there's no appeal process that actually works.</p><p>You can request mediation — if the platform offers it. You can email support. You can try to escalate.</p><p>In my experience, these all lead to the same place: silence.</p><p>I want to be fair here.</p><p>Triage serves a purpose.</p><p>Bug bounty platforms get flooded with garbage — low-effort reports, false positives, people submitting known issues, scammers.</p><p>Someone has to filter that. It's a necessary job.</p><p>But when the filter rejects signal along with noise — when a technically valid report gets killed with "by-design" and no technical counterargument — the system is broken.</p><p>And the researcher has no recourse.</p><p>A report you spent days writing can be closed before your melon soda goes flat.</p><p>I knew the only defense against a reflexive "by-design" closure was evidence so overwhelming it couldn't be dismissed.</p><p>Not one proof of concept. Two.</p><hr><h3 id="h-two-pitons" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Two pitons</h3><p>In climbing, a piton is a metal spike you hammer into a crack in the rock.</p><p>It's what keeps you alive if you fall.</p><p>One piton is standard. Two is insurance.</p><p><strong>E1</strong> — the first piton.</p><p>A test case where the honest refund should be 10,000 gas but the sequencer claims 21,000.</p><p>The verifier accepts it. Delta: 11,000 gas.</p><p>This proves the Rust verifier doesn't validate refund correctness — it passes an inflated value without catching it.</p><p>Good.</p><p>But maybe the triage team waves it away.</p><p>"The delta is small." "This is a known limitation." "The spec allows flexibility."</p><p>So there needs to be a second one. Something that can't be explained away.</p><p><strong>rung1</strong> — the second piton.</p><p>First transaction in a block. Nothing has been warmed. No previous transactions have touched any accounts.</p><p>The honest SDM refund for this transaction is exactly <strong>zero</strong>.</p><p>There's nothing to refund because nothing has been pre-paid.</p><p>And yet — if the sequencer packs <code>refund: 21,000</code> into the payload for this transaction, the Rust verifier accepts it.</p><p>Full gas. From zero to 21,000. Out of thin air.</p><p>That's not a flexibility question. That's not a policy choice. That's fabrication.</p><p>And the consensus-critical verification path approves it.</p><p>E1 shows the auditor is sloppy. rung1 shows the auditor is blind.</p><p>Both pitons. Both in the rock. Now climb.</p><hr><h3 id="h-payload" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">payload</h3><p>Before I closed the terminal for the night, I looked at the Rust code one more time.</p><p><code>verifier_post_exec_refund_for_tx</code>.</p><p>The function where the verifier receives the sequencer's declared refund value and — without recalculating, without comparing, without questioning — writes it into the canonical chain state.</p><p>I traced the value upstream.</p><p>Where does it come from?</p><p>What variable carries the sequencer's assertion into the heart of the verification logic?</p><p><strong>payload.</strong></p><p>In blockchain terms, the payload is everything.</p><p>It's the bundle of data the sequencer constructs for each block — transactions, state changes, fee calculations, refund values.</p><p>The verifier receives this payload and is supposed to <em>verify</em> it.</p><p>That's literally the job description.</p><p>But for SDM refunds, the Rust verifier doesn't verify the payload. It accepts it.</p><p>The sequencer's word becomes the chain's truth.</p><p>An auditor that doesn't audit. A spec that calls it "freedom." And a payload that nobody checks.</p><p>I still had days of work ahead.</p><p>Writing the PoCs. Running the tests. Measuring the economic impact. Drafting the report in a format that a triage team couldn't dismiss in seventeen minutes.</p><p>Days of preparation for a fight I wasn't sure I could win.</p><p>But the bug was real. The code was right there.</p><p>And somewhere in the back of my mind, a thought was forming — one that wouldn't fully crystallize until much later, after the reports were submitted and the gates were slammed shut, again and again and again.</p><p>The thought was this:</p><p>In a system where nobody verifies the payload, everything the sequencer writes is speculation.</p><p>Trusted by default. Checked by no one.</p><p>Every number in the ledger is exactly as reliable as the entity that wrote it — which is to say, it's an assertion. An unverified claim.</p><p>Everything is speculation.</p><hr><blockquote><p><strong>payload.</strong></p></blockquote><hr><p><em>Episode 2: "The Second Piton" — coming next.</em></p><hr><p><strong>Glossary</strong> (for the non-degens)</p><table><colgroup><col><col><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>In the Story</p></th><th colspan="1" rowspan="1"><p>In the Code</p></th><th colspan="1" rowspan="1"><p>What It Actually Means</p></th></tr><tr><td colspan="1" rowspan="1"><p>Teller</p></td><td colspan="1" rowspan="1"><p>Sequencer</p></td><td colspan="1" rowspan="1"><p>Writes transactions to the chain. You have to trust it — or verify.</p></td></tr><tr><td colspan="1" rowspan="1"><p>Auditor</p></td><td colspan="1" rowspan="1"><p>Verifier</p></td><td colspan="1" rowspan="1"><p>Supposed to recompute and check the sequencer's work. Supposed to.</p></td></tr><tr><td colspan="1" rowspan="1"><p>Go auditor</p></td><td colspan="1" rowspan="1"><p>x-chain-ops validator</p></td><td colspan="1" rowspan="1"><p>Recalculates independently. Rejects mismatches. Does its job.</p></td></tr><tr><td colspan="1" rowspan="1"><p>Rust auditor</p></td><td colspan="1" rowspan="1"><p>x-reth / nova</p></td><td colspan="1" rowspan="1"><p>Checks a ceiling, not correctness. Consensus-critical.</p></td></tr><tr><td colspan="1" rowspan="1"><p>"Freedom"</p></td><td colspan="1" rowspan="1"><p>SDM spec language</p></td><td colspan="1" rowspan="1"><p>One word that justifies not checking</p></td></tr><tr><td colspan="1" rowspan="1"><p>Gatekeeper</p></td><td colspan="1" rowspan="1"><p>Triage</p></td><td colspan="1" rowspan="1"><p>Can close your report in minutes. No effective appeal.</p></td></tr><tr><td colspan="1" rowspan="1"><p>Piton</p></td><td colspan="1" rowspan="1"><p>PoC (Proof of Concept)</p></td><td colspan="1" rowspan="1"><p>A test proving the bug is real and reproducible</p></td></tr><tr><td colspan="1" rowspan="1"><p>payload</p></td><td colspan="1" rowspan="1"><p>Execution Payload</p></td><td colspan="1" rowspan="1"><p>The data blob the sequencer controls — and the verifier trusts</p></td></tr></tbody></table><hr><p><em>Everything is Speculation — YomibitoShirazu</em><span data-name="copyright" class="emoji" data-type="emoji">©</span><em> 2025 algorithm.dance</em></p>]]></content:encoded>
            <author>yomibitoshirazu@newsletter.paragraph.com (YomibitoShirazu)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/cb74710f9d2afcc689fb08e491a669b9ea2c29c3252e9e286b5e37de2e81691f.jpg" length="0" type="image/jpg"/>
        </item>
    </channel>
</rss>