Summary
On 14 June 2026 a deprecated Aztec Connect contract, the RollupProcessor (sometimes referenced as RollupProcessorV3), was drained of approximately $2.19M in a single Ethereum transaction. The contract had been shut down years earlier, was immutable, and still held residual user funds. Public technical analysis of the Aztec Connect exploit points to a boundary mismatch between the zero-knowledge proof's public-input commitments and the contract's L1 settlement processing, which let the attacker credit unbacked L2 balances and then withdraw them as real L1 assets. This is an analysis of what the on-chain record shows, what the public reporting attributes as the root cause, and what an immutable legacy contract still holding value teaches every team that has ever deprecated a system without sweeping it clean.
This is not the current Aztec network, and it is not the AZTEC ERC20 token. Per statements from the Aztec Foundation / Aztec Labs on X, the affected contract is the old Aztec Connect rollup, deprecated in 2023, and the incident does not affect the live Aztec network or any AZTEC token. We treat that distinction as load-bearing throughout this Aztec Connect postmortem.
What happened
Aztec Connect was a privacy-focused zero-knowledge rollup that let users move assets into a shielded L2, transact, and withdraw back to Ethereum L1. It was wound down in 2023. Crucially, the Aztec deprecated contract remained on-chain, immutable, and still custodied a residual pool of user funds that had never been fully withdrawn. Aztec Labs has stated it held no admin keys and had no ability to pause or upgrade the contract, which is the expected and deliberate property of a trust-minimised rollup that has been handed over to its own immutable logic.
According to KuCoin's technical analysis, the attacker assembled a single transaction containing 14 processRollup() calls in two phases: the first seven minted or credited L2 balances, and the final seven withdrew them to L1. Reporting in the style of KuCoin and GoPlus cites rollup IDs in the range of roughly 13277 to 13290 for the sequence. The net effect, captured in a single confirmed transaction, was the removal of ETH and several ERC20 positions from the legacy Aztec: Connect contract to an attacker-controlled address. KuCoin separately frames it as an abandoned smart contract exploited about three years after shutdown.
On-chain evidence
Unlike incidents where identifiers are still being verified, the core of this one is a single, confirmed Ethereum transaction. Every identifier below resolves on a public block explorer.
| Field | Value | Explorer |
|---|---|---|
| Exploit transaction | 0x074ec9317d8336db37e8c348fbdd7515573ff4088239c77ab429f522509aeeb1 | Etherscan tx |
| Status | Success | Confirmed on Etherscan |
| Block | 25315715 | Etherscan |
| Timestamp | 14 June 2026, 12:26:23 PM UTC | Etherscan |
| Attacker EOA (labeled “Aztec Exploiter 1”) | 0x0F18D8b44a740272f0be4d08338d2b165b7EdD17 | Etherscan address |
| Attack contract | 0x06f585F74e0DA633Ae813A0f23Fb9900B61d0fcD | Etherscan address |
| Affected contract (labeled “Aztec: Connect”) | 0xff1f2b4ADb9dF6fC8EaFEcDCbF96A2B351680455 | Etherscan address |
| Direct value | 0 ETH (value moved via internal and token transfers) | Etherscan |
| Transaction fee | 0.000520895358461778 ETH (gas price 0.115407302 Gwei) | Etherscan |
The asset movement out of the affected contract, recorded as internal and ERC20 transfers in the same transaction, breaks down as follows:
| Asset | Amount transferred to attacker |
|---|---|
| ETH (internal transfer) | 908.986707307963496632 ETH |
| DAI | 270,513.054157632152892774 |
| wstETH | 167.890392526462638142 |
| yvDAI | 4,873.856656463299373447 |
| yvWETH | 16.569551230652464753 |
| LUSD | 9,273.734320992446140764 |
| yvLUSD | 359.047484523695640986 |
Aggregated, the loss is reported at approximately $2.19M, with source estimates ranging from about $2.1M to $2.19M depending on pricing and the exact basket valued. The presence of Yearn vault tokens (yvDAI, yvWETH, yvLUSD) alongside DAI, wstETH, and LUSD reflects the bridged DeFi positions that Aztec Connect users held inside the rollup at the time it was deprecated. Our Crypto Talk published the full transaction hash and a legacy-contract framing consistent with the explorer record above.
The attack path
The mechanics, as reported by KuCoin and corroborated in summary by BlockSec / Phalcon and GoPlus, follow a clean two-phase shape inside one transaction:
- Phase one, manufacture balances. The first seven
processRollup()calls submitted rollup blocks that the contract accepted as valid state transitions, crediting L2 balances to the attacker. Reported rollup IDs sit in the ~13277 to 13290 range across the sequence. - Phase two, realise the balances on L1. The final seven
processRollup()calls processed withdrawals of those freshly credited balances, instructing the immutable RollupProcessor to release real ETH and ERC20 tokens from its residual reserve to the attacker. - Settlement to a fresh address. The ETH and tokens landed at the attacker EOA
0x0F18D8b44a740272f0be4d08338d2b165b7EdD17via the attack contract0x06f585F74e0DA633Ae813A0f23Fb9900B61d0fcD, all in transaction0x074e…eeb1.
In plain terms: the attacker convinced the contract that they were owed money inside the rollup, then asked the contract to pay out that money in real assets it was still holding. The L2 credits were not backed by any genuine deposit. The L1 withdrawals were entirely real.
Reported root cause
The publicly circulated technical analysis attributes the exploit to a boundary mismatch between the zero-knowledge proof's public-input commitment and the contract's L1 settlement loop, often described as a discrepancy between numRealTxs and decoded_slots. We state this as the reported root cause, drawn from public analysis, not as a final official postmortem. At time of writing we are not aware of Aztec having published a definitive root-cause postmortem, so the following is the strongest available public explanation rather than a confirmed verdict.
The plain-language version: a ZK rollup proves, succinctly, that a batch of transactions was processed correctly, and the L1 contract trusts that proof and settles balances accordingly. The settlement code has to read the same number of transaction slots that the proof actually committed to. If the contract decodes or iterates over a different count of slots than the proof's public inputs bind, an attacker can stuff the gap with operations the proof never genuinely vouched for. The proof verifies. The settlement loop processes more (or different) entries than were proven. The result is L2 balances that the cryptography never actually backed, redeemable as L1 funds.
The technical version, as reported: the public-input commitment that the verifier checks did not fully constrain the range of transaction slots the settlement logic walked, so numRealTxs as bound by the proof diverged from the decoded_slots the contract processed during withdrawal handling. That gap is what the two-phase processRollup() sequence is reported to have exploited: credit via the manufactured slots, then withdraw against them. We flag this as the leading public hypothesis pending any official confirmation.
Confirmed vs pending
| Field | Status | Detail |
|---|---|---|
| Exploit transaction and identifiers | Confirmed on-chain | Tx 0x074e…eeb1, block 25315715, all addresses resolve on Etherscan with the labels noted above |
| Affected contract is deprecated Aztec Connect | Confirmed | Etherscan label “Aztec: Connect”; Aztec Foundation / Aztec Labs statement; Connect was wound down in 2023 |
| Not the current Aztec network or AZTEC token | Stated by Aztec | Per Aztec Foundation / Aztec Labs on X; the live network and AZTEC ERC20 are unaffected |
| No admin keys / no pause or upgrade ability | Stated by Aztec Labs | The contract was immutable by design; Aztec Labs says it could not intervene |
14 processRollup() calls, two phases | Reported | Seven mint/credit then seven withdraw, per KuCoin |
| Rollup IDs ~13277–13290 | Reported | Cited in KuCoin / GoPlus-style analysis |
Root cause: ZK public-input vs L1 settlement gap (numRealTxs vs decoded_slots) | Public analysis, not official postmortem | Leading public hypothesis; no definitive Aztec postmortem confirmed at time of writing |
| Loss amount | Reported range | ~$2.1M to $2.19M depending on basket pricing |
| Funds location post-incident | Reported, timing-sensitive | Stolen funds reportedly remained in the attacker EOA shortly after the incident (KuCoin / Our Crypto Talk); status may have changed since |
Why a deprecated, immutable contract still matters
The instinct after reading “deprecated in 2023” is to file this under harmless legacy. That instinct is exactly the problem. Three properties combined to turn an old contract into a $2.19M target:
It still held value. Residual user funds, ETH plus a basket of DeFi positions, never fully withdrawn after shutdown, sat in the contract for years. Deprecation removed the contract from the roadmap, not from the chain, and certainly not from its custody of real assets.
It was immutable and unowned. The same trust-minimisation that makes a rollup credible, no admin keys, no pause, no upgrade, is precisely what left no one able to stop the drain once it started. Aztec Labs has said it could not intervene. Immutability is a feature while the code is correct and a trap the moment a latent flaw surfaces and value remains.
Nobody was watching it. A live system has monitoring, an on-call rotation, and incident owners. A deprecated one usually has none of that, so a 14-call drain executes in a single block against an audience of zero. The economic incentive to attack a forgotten contract grows over time as scrutiny falls and the balance sits untouched.
This is the same failure class we documented in the DxSale legacy locker drain on BNB Chain: an abandoned contract still holding funds, exploited long after anyone was paying attention. The chain does not retire code because a team stopped maintaining it.
Why this matters for Web3 security
A correct proof does not mean a correct system. Aztec Connect's verifier almost certainly validated the proofs it was given. The reported flaw is not in the cryptography but in the seam between the proof's public inputs and the contract code that acts on them. ZK rollups concentrate enormous trust in that boundary, and a single under-constrained commitment there can let unproven state masquerade as proven. The audit question for any rollup is not just “is the circuit sound” but “does the L1 settlement code process exactly, and only, what the proof commits to.”
Bridges and rollups are where residual value concentrates. The largest losses in this space keep landing at the boundary between an L2 or a bridge and L1 settlement, as we covered in the Verus Ethereum bridge drain and the Gravity Bridge denom-poisoning exploit. A rollup that still holds bridged DeFi positions is a bridge for the purposes of attacker economics, deprecated or not.
Deprecation is an operational event, not the end of one. The cost of leaving value in an immutable contract you can no longer control compounds silently. This belongs squarely inside operational risk management, not the archive.
Practical controls and lessons
Sweep assets before you deprecate. A shutdown plan is not complete until residual balances are accounted for. Where possible, design contracts so that deprecation includes a path to return or migrate every remaining user position, and verify on-chain that the balance is actually zero before declaring a system retired.
Build escape hatches that survive immutability. Trust-minimisation and an emergency exit are not mutually exclusive. A time-locked, narrowly scoped recovery or migration path, decided before launch and visible to users, lets a community drain residual value to safety without reintroducing an admin god-key. The absence of any brake here was deliberate, and it is exactly what left no response possible.
Publish a shutdown dashboard. When a system is deprecated, a public page should state its status, its remaining on-chain balance, the addresses involved, and what users must do to exit. Silence around a retired contract is what lets residual TVL drift out of everyone's view until an attacker finds it first.
Monitor residual TVL on retired contracts. Any contract that still holds value deserves balance and event monitoring, deprecated or not. A simple alert on outflows from a known legacy address would have surfaced this drain as it happened rather than after the fact. Forgotten value is not the same as no value.
Validate public inputs independently on L1. For any rollup or proof-verifying contract, the settlement code must enforce that the number and content of processed transaction slots match exactly what the proof's public inputs commit to. The reported numRealTxs versus decoded_slots gap is the textbook case for explicit, defensive bounds checks at the proof-to-settlement boundary.
Write invariant tests across the proof and settlement boundary. Unit tests on a circuit and unit tests on a contract are not enough if nothing tests the seam between them. Property and invariant tests should assert that no sequence of processRollup()-style calls can ever credit or withdraw more than the proofs genuinely back, including adversarial batch counts and slot ranges.
Independent review before upgrades and before shutdowns. External review should cover not just the launch state but the wind-down state. The configuration a contract is left in when a team walks away is a security-relevant decision and deserves the same scrutiny as a deployment.
Assign incident ownership for legacy systems. Someone must own every contract that still holds value, even after the product is dead. That owner is responsible for monitoring, for the deprecation dashboard, and for the documented response if the unthinkable happens to code no one can change. Immutable does not mean unowned.
Sources
- Aztec Foundation / Aztec Labs statement on X (not the current Aztec network or AZTEC token)
- KuCoin, “Aztec Connect hacked for $2.19M via ZK rollup vulnerability”
- KuCoin, “Aztec Connect's abandoned smart contract exploited for $2M three years after shutdown”
- Our Crypto Talk, “Aztec Connect exploit: $2.19M from a legacy contract”
- Etherscan, exploit transaction
- Etherscan, attacker EOA (“Aztec Exploiter 1”)
- Etherscan, attack contract
- Etherscan, affected contract (“Aztec: Connect”)
- GoPlus analysis on X
- BlockSec / Phalcon analysis on X
If you operate a rollup, a bridge, or any contract that holds value you no longer actively maintain, the Aztec Connect exploit is the case to study this week. The questions it raises are concrete: does your L1 settlement code process exactly what your proofs commit to, do your invariant tests cover the proof-to-settlement boundary, and does every deprecated contract that still holds funds have an owner, a monitor, and a documented response. Security4Web3 reviews ZK rollup and bridge settlement logic for public-input and boundary flaws, audits deprecation and shutdown plans for residual TVL, and builds the legacy-system monitoring and incident ownership that turn a forgotten contract into a watched one rather than a $2.19M payday.