
{"id":227297,"date":"2026-09-14T14:24:29","date_gmt":"2026-09-14T14:24:29","guid":{"rendered":"https:\/\/mycryptomania.com\/?p=227297"},"modified":"2026-09-14T14:24:29","modified_gmt":"2026-09-14T14:24:29","slug":"mayachain-1-7m-slash-subsidy-pool-inflation-exploit-explained","status":"publish","type":"post","link":"https:\/\/mycryptomania.com\/?p=227297","title":{"rendered":"MAYAChain $1.7M Slash Subsidy Pool Inflation Exploit (Explained)"},"content":{"rendered":"<p>On August 18, 2026, an attacker chained six bugs in MAYAChain\u2019s trade account and outbound-handling logic to drain the Asgard reserve. No key was stolen, and this wasn\u2019t a flash-loan drain: a single batched deposit triggered a false theft alert, and an uncapped slash subsidy turned that into 48.87M forged CACAO in one thin pool. The attacker cashed out through it, extracting roughly\u00a0$1.7M.<\/p>\n<h3>Protocol Background<\/h3>\n<p>MAYAChain settles cross-chain swaps through its Asgard vaults, with every observed transaction tracked against a shared ObservedTxVoter record. A single MsgDeposit can batch multiple actions together, including trade-account swaps and a DONATE action, all reported against that same voter. When an outbound transaction appears to go missing, the chain treats it as theft and slashes a subsidy into the affected pool to make it whole, a safety mechanism this exploit turned into the attack\u00a0itself.<\/p>\n<h3>Hack Analysis<\/h3>\n<p>MAYAChain\u2019s protection against a receipt being processed twice lives in a shared ObservedTxVoter record, one per native transaction ID. Inside the handler for a batched MsgDeposit, every message in the batch creates its own fresh voter and overwrites whatever was there before via SetObservedTxInVoter(). A transaction with enough messages can let its last message quietly erase what every earlier message had recorded.<\/p>\n<p>The attacker used exactly that. A single MsgDeposit carrying 23 messages ran 20 trade-account swaps into ARB.ETH, two more into ARB.LINK, and closed with a one-unit DONATE:ARB.LINK message. That final message overwrote the voter the earlier trade withdrawals had set, resetting OutboundHeight to 0 and marking the whole transaction done.<\/p>\n<p>Check here in rwa data: <a href=\"https:\/\/www.mayascan.org\/tx\/516BA14D6976EC7B8A3087E1C52B195433EF0F9D85F4B9520675BC4FEB99E9B7\">516BA14D6976EC7B8A3087E1C52B195433EF0F9D85F4B9520675BC4FEB99E9B7<\/a><\/p>\n<p>With OutboundHeight zeroed, the outbound matcher fell back to FinalisedHeight and scanned forward in fixed increments, but it never checked the one block where the LINK outbounds had actually landed. Finding no record there, the chain concluded the outbound had gone missing and triggered its theft-detection slash.<\/p>\n<p>That slash path converts the supposedly stolen amount into CACAO at the pool\u2019s own exchange rate, with nothing capping the result against how much asset the pool actually holds. The ARB.LINK pool had only about 0.11 LINK in it, so running the stolen amount through that rate produced a number completely detached from reality: roughly 49.45 million CACAO, booked straight into the\u00a0pool.<\/p>\n<p>The code writes that inflated pool balance to state before it actually tries to fund it from the reserve. The reserve only held about 168,000 CACAO, so the funding transfer failed, but the pool\u2019s new balance had already been saved. The handler that caught the failure just logged it and marked the transaction done anyway, with no rollback, leaving the inflated pool sitting in state as if it were\u00a0real.<\/p>\n<p>With a pool now showing tens of millions of CACAO against almost no LINK, the attacker added a small amount of liquidity to it. The pool-unit math treated the deposit as founding a fresh pool, handing over 99.93% ownership, and an immediate withdrawal at 9,900 basis points paid out 48.87 million CACAO from the Asgard module. The attacker moved straight into swapping it for BTC, ETH, RUNE, and stablecoins across every Maya\u00a0pool.<\/p>\n<h3>Root Cause<\/h3>\n<p>It was six separate weaknesses lining up in one transaction. <strong>The root failure is that a shared observed-transaction voter could be silently overwritten by a later message in the same batched deposit, and everything downstream, theft detection, the slash subsidy, and the funding transfer, trusted that voter\u2019s state without re-checking or bounding it against\u00a0reality.<\/strong><\/p>\n<p>Once the final DONATE message reset the voter, the outbound matcher&#8217;s fallback logic never checked the right block, the slash subsidy calculation never capped itself against the pool&#8217;s real balance, and the code that wrote the inflated pool to state ran before the code meant to fund it, with the resulting failure just logged and swallowed instead of rolled back. Any one of those checks alone would have stopped the drain, bind the voter to something a later message can&#8217;t clobber, cap the subsidy to what the pool can actually hold, or roll back state when a downstream transfer\u00a0fails.<\/p>\n<h3>How QuillAudits Infrastructure Review Could Have Prevented This<\/h3>\n<p><strong>Voter integrity across batched messages.<\/strong> Any check whose entire security model rests on a shared record needs a guarantee that record can\u2019t be overwritten by an unrelated message later in the same batch. A review tracing every writer of ObservedTxVoter would have caught SetObservedTxInVoter clobbering per-message state in handler_deposit.go.<\/p>\n<p><strong>Bound every subsidy calculation to the pool\u2019s actual balance.<\/strong> The AssetValueInRune call behind the slash subsidy had no ceiling tied to pool.BalanceAsset, so a thin pool could be told it held tens of millions of CACAO it never had. Any function that credits a balance from a computed value needs an explicit sanity cap against the resource it&#8217;s crediting.<\/p>\n<p><strong>Never commit state ahead of the transfer meant to back it.<\/strong> SetPool ran before SendFromModuleToModule in helpers.go, so when the transfer failed, the inflated state had already been saved. Persisted state should follow a successful funding transfer, not precede it, and a failed downstream call should roll back what came before it rather than just log and continue.<\/p>\n<h3>Funds Flow After\u00a0Attack<\/h3>\n<p>The attacker immediately began swapping the drained CACAO into BTC, ETH, RUNE, and stablecoins across every Maya\u00a0pool.<\/p>\n<p>20.82 BTC, worth about $1,343,367, moved to <a href=\"https:\/\/blockchair.com\/bitcoin\/address\/bc1q0hsgwunccczelq05ucpmfz268eyy5jr2y5l646\">bc1q0hsgwunccczelq05ucpmfz268eyy5jr2y5l646<\/a>. As of now they are still in attacker\u00a0wallet<\/p>\n<p>Meanwhile on ethereum attacker has deposited some eth in tornado\u00a0cash.<\/p>\n<h3>Post-Attack Mitigation<\/h3>\n<p>Maya founder posts an initial public message calling it sad news and saying it will work to fix the issue and recover in\u00a0full.<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/cdff3bfdba5433be5859d398ac731175\/href\">https:\/\/medium.com\/media\/cdff3bfdba5433be5859d398ac731175\/href<\/a><\/p>\n<p>Maya confirms the exploit to its community, roughly 20 BTC and $300k in other assets, says it has done a global halt to contain the damage, and shares the attacker\u2019s Bitcoin address in case they\u2019re open to a bug\u00a0bounty.<\/p>\n<p>Maya commits $200,000 of the team\u2019s own funds into the pools as a first step in the recovery\u00a0process.<\/p>\n<p>Maya says it will accelerate the launch of its Aztec Chain platform and direct a share of the funds it raises back into the pools to help recover from the\u00a0exploit.<\/p>\n<p>Maya sends the attacker a message through a Bitcoin OP_RETURN transaction, asking them to return the funds and offering a bug bounty in exchange.<\/p>\n<h3>Relevant Addresses and Transactions<\/h3>\n<p><strong>Attacker Wallet<\/strong><\/p>\n<p>Maya trade-account attacker, executed the exploit transaction, still holds 8,874,269.11 CACAO: <a href=\"https:\/\/www.explorer.mayachain.info\/address\/maya1dl3yrfpedyr5jfr0r86s2apjltnjqgszmwsv8x\">maya1dl3yrfpedyr5jfr0r86s2apjltnjqgszmwsv8x<\/a><a href=\"https:\/\/blockchair.com\/bitcoin\/address\/bc1q0hsgwunccczelq05ucpmfz268eyy5jr2y5l646\">bc1q0hsgwunccczelq05ucpmfz268eyy5jr2y5l646<\/a><a href=\"https:\/\/arbiscan.io\/address\/0xa2f246f82995CBcCA8eD0d9F251383881A5E423e\">0xa2f246f82995CBcCA8eD0d9F251383881A5E423e<\/a><\/p>\n<p><strong>Affected Pool<\/strong><\/p>\n<p>ARB.LINK: 0XF97F4DF75117A78C1A5A0DBB814AF92458539FB4<\/p>\n<p><strong>Key Transactions<\/strong><\/p>\n<p>Exploit transaction: <a href=\"https:\/\/www.mayascan.org\/tx\/516BA14D6976EC7B8A3087E1C52B195433EF0F9D85F4B9520675BC4FEB99E9B7\">516BA14D6976EC7B8A3087E1C52B195433EF0F9D85F4B9520675BC4FEB99E9B7<\/a>Add &amp; Remove Liquidity Tx: <a href=\"https:\/\/www.explorer.mayachain.info\/tx\/888AF3EBE9A9A0DBA0F64FE4FD77793E69872466691387A786C9FE19E2693519\">888AF3EBE9A9A0DBA0F64FE4FD77793E69872466691387A786C9FE19E2693519<\/a>Bug Bounty Offer: <a href=\"https:\/\/mempool.space\/tx\/aa209b30d84cd63474ba873cfb1c72e5da8e7765b818a0750842e870c1d5b367\">aa209b30d84cd63474ba873cfb1c72e5da8e7765b818a0750842e870c1d5b367<\/a><\/p>\n<h3>Conclusion<\/h3>\n<p>No key was stolen, and no single bug did this on its own. A shared voter that a later message could silently overwrite was trusted by every check downstream of it, theft detection, the slash subsidy, and the transfer that was supposed to back it, and none of them verified what the others had already gotten wrong. A pool with barely any liquidity ended up crediting tens of millions of CACAO to itself, and the attacker just had to show up and withdraw it. Six checks failed in sequence; one working boundary anywhere in that chain would have stopped\u00a0it.<\/p>\n<p><strong><em>Original Posted at <\/em><\/strong><a href=\"https:\/\/www.quillaudits.com\/blog\/hack-analysis\/mayachain-slash-subsidy-exploit\"><strong><em>QuillAuidts<\/em><\/strong><\/a><\/p>\n<p><a href=\"https:\/\/medium.com\/coinmonks\/mayachain-1-7m-slash-subsidy-pool-inflation-exploit-explained-1c14160108d7\">MAYAChain $1.7M Slash Subsidy Pool Inflation Exploit (Explained)<\/a> was originally published in <a href=\"https:\/\/medium.com\/coinmonks\">Coinmonks<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>On August 18, 2026, an attacker chained six bugs in MAYAChain\u2019s trade account and outbound-handling logic to drain the Asgard reserve. No key was stolen, and this wasn\u2019t a flash-loan drain: a single batched deposit triggered a false theft alert, and an uncapped slash subsidy turned that into 48.87M forged CACAO in one thin pool. [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":227298,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-227297","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-interesting"],"_links":{"self":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/227297"}],"collection":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=227297"}],"version-history":[{"count":0,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/227297\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/media\/227298"}],"wp:attachment":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=227297"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=227297"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=227297"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}