How Six Failures Turned a MAYAChain Outbound Bug Into a Pool Drain
A technical breakdown of how transaction-voter state, outbound matching, subsidy accounting, and pool math compounded into a MAYAChain exploit.
How Six Failures Turned a MAYAChain Outbound Bug Into a Pool Drain
⏱️ 6-minute read
A protocol does not need one catastrophic bug to lose funds. The reported MAYAChain incident shows how six unsafe assumptions can chain together: transaction state can be overwritten, an outbound can be matched at the wrong height, a subsidy can be valued without a cap, and a failed operation can leave its accounting behind.
An overwritten voter changes a transaction’s meaning
According to the postmortem, the attacker sent one 23-message MsgDeposit ending in DONATE:ARB.LINK. Each message stored an ObservedTxVoter under the same transaction identifier. The final message overwrote voters associated with earlier withdrawals, set OutboundHeight to zero, and marked the transaction complete.
A voter is state used to track an observed transaction and its processing lifecycle. If a later operation can replace that state without preserving earlier information, it loses the economic identity of prior messages. This was the first condition in the chain.
Matching searched the wrong heights
Once outbound height was lost, matching fell back to FinalisedHeight and advanced by signing-period increments. That walk did not inspect the actual height where the LINK outbounds landed. The protocol falsely classified them as missing and triggered theft handling.
In cross-chain systems, block height is not decorative metadata. It can be part of the identity used to reconcile an instruction, signatures, and a completed transfer. A fallback must prove it reaches the expected event, not merely walk heights on a schedule.
An uncapped subsidy inflated a pool
The theft path valued the raw claimed amount without capping it by the ARB.LINK pool’s asset balance, which was very small. The postmortem reported that the calculation booked about 49.45 million CACAO into the pool.
The next problem was write ordering. The inflated pool state was stored before the protocol tried to fund it from Reserve to Asgard. Reserve could not cover the amount. The transfer failed, but the state had already been written.
A logged error is not a rollback
The outbound handler logged the error, marked the voter complete, and continued without rolling back the context. The result was a pool with inflated CACAO that lacked equivalent backing.
Partial persistence is especially dangerous in financial protocols. Every balance-changing operation needs a clear invariant: either all of its updates occur and are funded, or none of them are confirmed. Logging a failure does not restore earlier state.
Minimal liquidity captured nearly all ownership
With an inflated pool and almost no asset liquidity, the attacker added minimal liquidity. Pool-unit math treated it much like a new pool and gave the attacker about 99.93% of its units. A subsequent 9900-basis-point withdrawal released 48.87 million CACAO, according to the postmortem.
The CACAO was then swapped into external assets. The report distinguishes about $1.36 million of direct L1 extraction from a wider fall in pool value. That distinction matters: third-party arbitrage and CACAO devaluation also affected balances, but are not the same as direct attacker withdrawals.
What an audit should prove
- Test batched transactions that reuse identifiers and ensure state cannot be incompatibly overwritten.
- Design outbound matching with explicit checks for height, identity, and search bounds.
- Cap every valuation, subsidy, slash, or compensation path by assets actually available.
- Make pool updates and funding transfers atomic, with rollback on failure.
- Treat errors in financial handlers as conditions that stop a transition, not events to log and continue past.
- Simulate pools with extreme or near-empty liquidity to ensure unit math cannot enable disproportionate capture.
The lesson is not that auditing is useless. It is that reviews must ask how components that appear correct in isolation can fail together. Cross-chain teams should test error paths, partial state, pool economics, and adversarial message sequences as one system.
Sources
- MAYAChain Inspector, technical postmortem.
- Decrypt, “Six-Bug Exploit Halts Maya Protocol After $1.4 Million in Bitcoin Stolen”.
- Cointelegraph, “MAYAChain halts network after estimated $1.7M exploit”.