Initia Exploit: A MoveVM Cache Bug Emptied Its Bridges
Originally published at panda-security.xyz On 23 October 2026 at 14:59 UTC, an attacker used a flaw in the script cache of Initia's MoveVM to credit itself with unbacked WETH, iUSD and USDC on the Initia L1. Within abou
Originally published at panda-security.xyz
On 23 October 2026 at 14:59 UTC, an attacker used a flaw in the script cache of Initia's MoveVM to credit itself with unbacked WETH, iUSD and USDC on the Initia L1. Within about seven minutes, real assets started leaving Ethereum-side bridge reserves. By the time validators halted the L1 and every rollup at 15:41:30 UTC, roughly $2.7M had been bridged out and swapped into 1,135.52 ETH.
No token contract on Ethereum was hacked, and no bridge signature was forged. The bridges did exactly what they were designed to do: they burned a token on Initia and released the matching asset on Ethereum. The problem is that the token on Initia was never backed. This post walks through what is confirmed, what is still unknown, and what bridge and L1 teams should take from it.
TL;DR
- Victim: Initia, a Cosmos SDK L1 that runs MoveVM and hosts a network of rollups.
- Root cause (per Initia): a bug in MoveVM's script caching let malicious code "bypass security checks" and spoof VM state, crediting balances without changing the recorded total supply. Initia has not yet published the technical post-mortem.
- Cash-out: about 105 WETH and ~1.4M AUSD0 over LayerZero, plus ~1.08M USDC through Noble and Circle's CCTP.
-
Proceeds: swapped to ETH and parked in
0x358ef013...41cac8, which still held 1,135.52 ETH and had never sent a transaction when we checked it on 27 October. - Who pays: the reserves behind bridged assets. Bitquery measured Noble's USDC reserve for Initia falling from $1.09M to $63, the ETH adapter losing about 96% and the AUSD adapter about 71%.
- Native INIT: not minted, and Initia says its supply is unaffected.
What Initia Is and Why Bridged Tokens Matter
Initia is a layer 1 built on the Cosmos SDK, with MoveVM as its smart contract engine and a family of rollups that settle to it. Most of the dollar and ether liquidity on the chain is not native. It arrives through bridges:
- ETH and AUSD come from Ethereum through LayerZero OFT adapters. An adapter locks the real asset on Ethereum, and an omnichain token is credited on Initia. AUSD's Initia-side copy is called AUSD0.
- USDC comes from Noble, the Cosmos chain that issues Circle's USDC, and leaves for Ethereum through CCTP.
- iUSD is Initia's own dollar token, issued one-for-one against AUSD0.
The security of every one of these copies reduces to a single invariant: the balances on Initia must never exceed what is locked behind them. If the destination chain can be convinced that someone owns tokens they never deposited, the reserve on the home chain will pay the difference to whoever burns them first.
What Initia Has Confirmed
Initia's official statement on 24 October says an attacker "exploited a bug in Initia MoveVM's script caching that allowed malicious code to bypass security checks." It adds that the attacker "artificially spoofed the MoveVM state," receiving unbacked WETH, iUSD and USDC "without changing the corresponding token's total supply." Co-founder Zon described it as a day-zero bug in Initia's MoveVM on the Cosmos SDK.
That last detail matters for monitoring. The forged balances did not appear in each token's recorded supply. A dashboard that watched only total_supply on Initia would have shown nothing unusual while millions of dollars in balances appeared.
Initia has not said which cache, which check, or which code path was involved. A fix and audit were promised "in a few days," and the L1 and rollups were still halted at the time of writing.
What the Chain Shows
Two independent on-chain write-ups, from D2 Finance (relayed by 0xCERT) and from Bitquery, line up on the shape of the attack.
Preparation
Bitquery reports that the attacker's Ethereum wallet, 0xdd922c84...f6edfa, received 0.098 ETH from Tornado Cash the same morning, sent small test transfers toward Osmosis, and bridged a little ETH to Initia. It then received 141 INIT for gas from an Osmosis wallet and uploaded its own program. The first attempt failed. The second worked.
The forged balances
D2 Finance pointed to a single mint transaction at 14:59:26 UTC that called one Move function to credit 2,000,000 AUSD0, with the same pattern for USDC and ETH. Bitquery counted four runs of the attacker's program within 13 seconds, producing about $7.48M of iUSD, USDC, AUSD0 and WETH at face value. Both agree that nothing was locked anywhere to back it.
Face value overstates the damage. About 3M of that was iUSD, which exists only on Initia and had no bridge to drain. Only the copies of real assets could be redeemed.
The cash-out
We checked the Ethereum side ourselves against a public RPC node:
- In block 26,256,091, the AUSD OFT adapter
0x38b8b7ca...f200c844transferred exactly 1,400,000 AUSD to the attacker. - In block 26,256,115, the ETH OFT adapter
0x66a503a1...0babbc1bdereleased exactly 105 ETH. - About 1.08M USDC was minted to Ethereum via CCTP after leaving Noble's reserve.
Each batch was swapped to ETH within minutes, mostly through 1inch according to Bitquery. Then, at 15:41:35 UTC, five seconds after the halt, the wallet sent 1,135.52 ETH to a fresh address, 0x358ef013...41cac8. That address had a transaction count of zero and the same balance when we read it on 27 October.
What did not get out
Bitquery found that three USDC withdrawals bounced because Noble's reserve no longer held enough. A final 200,000 AUSD0 message stalled because LayerZero Labs' own verifier did not sign it, and the AUSD adapter blocked it later that day. Roughly $1.55M of copies of real assets, plus the unsellable iUSD, were still on Initia when the chain stopped.
Ordinary users paid as well. After the attacker's withdrawals, eleven normal USDC redemptions drained most of what remained in Noble's reserve, and Bitquery counted 55 later withdrawals that failed before the halt.
Why a Cache Bug Becomes a Mint
Initia has not published the mechanism, so we will not guess at its code. The general failure class is well known to anyone who audits VMs, and it is worth stating plainly.
A Move VM does expensive work before it runs a script: it deserializes the bytecode, runs the bytecode verifier, and checks type and resource-safety rules. Those rules are what stop a script from creating a Coin or FungibleAsset value out of thin air or writing to storage it does not own. Caching the result is a reasonable optimisation. It becomes dangerous when the cache key does not fully bind what was verified. If the key misses the exact bytes, the dependency set, or the context the check depended on, a later execution can reuse a "verified" result for code that was never verified.
In a resource-oriented VM, skipping verification is close to the worst case. Resource safety is the mint authority. Bypass it, and a balance can exist without the module that controls supply ever being asked. That is consistent with Initia's description of balances that appeared while recorded supply did not move.
The lesson for auditors: in VM and runtime reviews, every cache in front of a security check is itself a security boundary. Review what the key contains, when entries are invalidated, and whether a cache hit can ever skip a check that a miss would run.
The Bridge Side: Trust Without Limits
The VM bug created the forged balances. The bridges turned them into $2.7M. A bridge cannot tell a forged balance from a real one if the source chain's state says it is real, so the last line of defense is how much it will release, and how fast.
Here is a simplified, illustrative Solidity sketch of an outflow limit on a lockbox adapter. It is not LayerZero's or Initia's code:
// Simplified illustration only. Not production code.
contract RateLimitedLockbox {
uint256 public constant WINDOW = 1 hours;
uint256 public maxOutflowPerWindow; // e.g. 10% of locked reserves
uint256 public windowStart;
uint256 public outflowInWindow;
function _release(address to, uint256 amount) internal {
if (block.timestamp >= windowStart + WINDOW) {
windowStart = block.timestamp;
outflowInWindow = 0;
}
outflowInWindow += amount;
require(outflowInWindow <= maxOutflowPerWindow, "outflow limit");
token.transfer(to, amount);
}
}
With a cap of, say, 10% of reserves per hour, a 1.4M AUSD release out of a larger pool, plus a 105 ETH release out of a reserve that ended 96% drained, would have hit the limit and paused. That would have bought the 42 minutes Initia needed to halt the chain.
It is worth noting what did work. LayerZero's verifier set includes a LayerZero Labs verifier, and the final AUSD message stalled when it did not sign. Noble's reserve could only pay what it held, which capped the USDC loss. Earlier we covered a negative fee that drained the WAX bridge and a Sui bridge claim bot that paid the Cetus attacker. The bugs differ, but each raises the same audit question about a bridge: how much can leave before anyone is able to react?
How to Prevent This
Treat VM caches as part of the trusted computing base
Any cache that stores a verification, type-check or permission result must be keyed by everything the result depended on: the full code hash, dependency versions, and the execution context. Add tests that try to reach execution through a cache hit with code the verifier would reject.
Monitor balances against supply, not just supply
Initia's forged balances left recorded supply untouched. An invariant check that sums balances for bridged assets, or reconciles each bridged token against its remote lockbox, would have flagged the attack in its first block.
Rate-limit bridge releases
Per-asset, per-window outflow caps on lockboxes and mint limits on the destination side turn an unlimited drain into a bounded one. Pair them with an automated pause when a cap is hit.
Require independent verifiers
The one AUSD message that stalled was the one that lacked a signature from an independent verifier. Bridges should require more than one independent party to approve a release, and those parties should be allowed to refuse when the amount looks wrong.
Rehearse the halt
Initia stopped the chain 42 minutes after the first forged balance appeared. That is fast for a full L1 halt, and still long enough to lose $2.7M. Chains with bridge exposure should know exactly who can pause which bridge, and practice doing it.
For a broader pre-launch list, see our smart contract security checklist.
Key Addresses and Transactions
- Attacker wallet on Ethereum:
0xdd922c841d85e12dac2dc2eef5a5e29cfff6edfa - Proceeds wallet (1,135.52 ETH):
0x358ef0130f7a5aa516dcd81bdc80b18cde41cac8 - 1.4M AUSD release:
0x034c1076...be17f3b6 - 105 ETH release:
0x5cd422fd...0887d7e9 - Transfer to the proceeds wallet:
0x60f15b7e...1043e06 - AUSD OFT adapter on Ethereum:
0x38b8b7ca28e672018a299b20565aca8cf200c844 - ETH OFT adapter on Ethereum:
0x66a503a1060ab3f2b1aaabed613fe30babbc1bde - Initia mint transaction (per D2 Finance):
67423E84815CEC63632BD4676CA22D33567F3E02C3187281C9B6BFD593CBA7AF
Sources
- Initia's official statement on X: root cause description, amounts and proceeds address
- 0xCERT advisory 0xCERT-2026-0267: summary of D2 Finance's on-chain analysis, Agora's clarification and indicators of compromise
- Bitquery investigation: preparation timeline, $7.48M face value, reserve drawdowns and blocked messages
- Le Coin report: independent confirmation of the proceeds wallet balance
- TokenPost report: independent summary of Initia's statement
- Transaction receipts, block timestamps and the proceeds wallet's balance and nonce, read by us from a public Ethereum RPC node
Closing Thoughts
The Initia exploit is a reminder that a bridge is only as sound as the state of the chain it trusts. A single cache bug in the VM was enough to fake balances, and bridges with no outflow limits converted them into real ETH within minutes. When the full post-mortem lands, we will be watching for exactly what the cache key missed.
Building on Move, running a bridge, or launching an appchain? Contact Panda Security for a review of your VM integration and bridge controls, or see our audit pricing.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.