Root Cause
Initia's Layer-1 runs an EVM-Cosmos hybrid architecture that embeds MoveVM (Move language execution) alongside the Cosmos SDK. A script-caching flaw in the MoveVM component allowed an attacker to poison the module cache and forge credited balances of bridged assets (WETH, iUSD, USDC) without making the corresponding deposits.
Move's execution model loads compiled modules into a per-session cache for performance. The bug permitted a crafted sequence of Move script calls to leave stale, attacker-controlled state in that cache. Subsequent calls consulted the poisoned cache rather than the canonical on-chain state, causing the VM to credit the attacker with assets they never deposited.
// Conceptual illustration of the cache-poisoning path
script {
use std::signer;
use initia_std::coin;
fun exploit_entry(account: &signer) {
// 1. Call a module that populates the cache with a crafted resource slot
malicious_module::seed_cache(account);
// 2. The caching layer returns the seeded (fake) balance on subsequent reads
// 3. Bridge module reads cached balance — not on-chain state — and authorises withdrawal
bridge::withdraw(account, fake_amount);
}
}
Note: Initia's full post-mortem was not yet published at time of writing; the above is a conceptual illustration derived from public disclosures.
Attack Steps
| Step | Action | Detail |
|---|---|---|
| 1 | Craft Move script | Designs script sequence that exploits the caching flaw |
| 2 | Forge WETH, iUSD, USDC balances | Cache-poisoning credits attacker with bridged assets |
| 3 | Bridge WETH + AUSD0 via LayerZero | ~105 WETH + ~1.4M AUSD0 transferred out |
| 4 | Bridge USDC via Noble / CCTP | ~1.08M USDC transferred out |
| 5 | Convert to ETH on Ethereum | Exchanged all proceeds for 1,135.52 ETH (≈ $2.7M) |
| 6 | Move ETH post-halt | Attacker wallet moved 1,135.5 ETH five seconds after Initia halted the L1 |
Impact
- ~$2.7M confirmed drained (1,135.52 ETH equivalent at time of exploit).
- Nominal token creation reached ~$7.48M at face value, but most consisted of synthetic iUSD that could not be redeemed.
- No native INIT tokens were minted; total INIT supply unaffected.
- Initia L1 and all rollups paused at 11:41 AM ET, October 23; no restart date confirmed as of publication.
- Agora (AUSD issuer) confirmed AUSD proper is fully backed; the bridged tokens were representations, not canonical AUSD.
Lessons for Auditors
- Cross-VM state consistency. When a blockchain embeds multiple execution environments (EVM + MoveVM, or MoveVM + CosmWasm), each VM's internal cache must be treated as untrusted for cross-module calls. Canonical on-chain storage should always be the authoritative source for balance and permissions queries.
- Cache invalidation at bridge boundaries. Any bridge or withdrawal operation that consults in-memory module state rather than committed chain state is a critical attack surface. Bridge modules must read from finalised, committed storage.
- Auditing novel VM integrations. Bespoke MoveVM deployments that diverge from the reference implementation (Aptos, Sui) may introduce unique caching semantics. Auditors should trace the module-loading and caching lifecycle explicitly.
- Post-halt fund movement. The attacker moved funds five seconds after the halt, indicating pre-arranged bridge transactions. Emergency halt procedures should include upstream bridge pause co-ordination.
- Synthetic vs. canonical asset accounting. Bridge contracts should distinguish between canonical assets and synthetic representations; excess issuance of the latter should trigger circuit-breakers.