Although Aztec Connect was officially shut down in 2024, some user assets remained locked inside its immutable smart contracts. In June 2026, an attacker exploited a design mismatch between the protocol’s Layer 1 and Layer 2 components, draining roughly $2.2 million in a single transaction.

Why an outdated smart contract was still vulnerable: The $2.2M Aztec Connect exploit

17.06.2026

18

8 min

On June 14, 2026, the deprecated RollupProcessor contract used by Aztec Connect (0xff1f2b4adb9df6fc8eafecdcbf96a2b351680455) was exploited. By abusing a discrepancy between the parameters numRealTxs and decoded_slots, the attacker was able to withdraw approximately $2.2 million from the protocol’s Layer 1 asset pool in a single atomic transaction.

Although Aztec Connect had been decommissioned in March 2024, its immutable smart contracts still held legacy user funds and remained exposed to potential vulnerabilities. GetBlock AML Research examined the incident from two perspectives: the contract’s source code and the blockchain data recorded during the attack.

The Root Cause of the Vulnerability

The exploit stemmed from a structural mismatch between the data range processed by the Layer 1 settlement logic and the range authenticated through the ZK-proof’s public input hash.

The attacker exploited this gap so that 31 of 32 public input slots were included in the Layer 2 state root and validated by the ZK-proof, while completely bypassing verification by the Layer 1 settlement mechanism.

Decoder.sol: numRealTxs Was Fully Controlled by the Attacker

The numRealTxs value was read directly from calldata at byte offset 4516 and was not restricted by any on-chain validation checks.

When DAO governance fails: how TOP was taken over and what Tornado Cash has to do with It

When DAO governance fails: how TOP was taken over and what Tornado Cash has to do with It

The TOP incident shows that taking over a crypto project does not always require hacking smart contracts. In some cases, acquiring enough voting power and exploiting the system exactly as designed can be enough.

Читать дальше

The decoded_slots parameter was rounded to a multiple of numTxsPerRollup to support the protocol’s SHA256 implementation. However, this rounding process created a gap between numRealTxs and decoded_slots, allowing arbitrary data to be inserted into the unused slots.

RollupProcessorV3.sol: Settlement Logic Processed Only numRealTxs Slots

How the Security Model Broke Down

Under normal conditions, every public input slot should either:

  • Be verified by the Layer 1 contract (for example, reducing pendingDepositBalance during deposits), or
  • Be constrained by the ZK circuit so that its publicValue must equal zero.

In this case, neither protection worked.

The SHA256 hash covered all 32 data slots. The total input size was 8,192 bytes, corresponding to 32 slots of 256 bytes each. As a result, the contents of the intermediate slots were included in the proof.

One System, Four Major Wallets: What’s Really Going On with DAI and USDS Stablecoins

One System, Four Major Wallets: What’s Really Going On with DAI and USDS Stablecoins

Despite generating more than $350 billion in transaction volume over the past 90 days, most USDS activity appears to stem from internal ecosystem operations. Retail users—the audience targeted by the yield-bearing sUSDS product—control less than 1% of the funds deposited in the system.

Читать дальше

However, the Layer 1 settlement loop processed only the first slot. Slots 2 through 32 were never examined by the contract. The ZK-circuit restriction that should have forced publicValue = 0 for these slots was either missing or successfully bypassed.

The protocol’s three security layers depended on one another, but none independently protected the intermediate slots. Once the ZK-level restriction failed, Layer 1 could not detect the malicious data.

Two Different Validation Paths

The same calldata was processed by two separate mechanisms, each using a different upper boundary.

Processing paths that contained the vulnerability

The ZK-proof system validated all 32 slots, while the Layer 1 logic effectively processed only one. This mismatch made it possible to create assets without any underlying collateral.

How the Attack Worked

The exploit transaction contained 14 calls to the processRollup() function. These were divided into two phases:

  1. Creating an unbacked Layer 2 balance.
  2. Withdrawing real Layer 1 assets.

Everything happened inside a single atomic transaction.

Phase 1: Creating an Unbacked Balance (Rollups #13277–13283)

The attacker’s externally owned account (0x0f18d8b44a740272f0be4d08338d2b165b7edd17) called the main attack contract (0x06f585f74e0da633ae813a0f23fb9900b61d0fcd), triggering function 0x6f3ce701.

The contract then routed execution through three intermediary contracts containing pre-built malicious rollup data.

Key parameters were:

  • numRealTxs = 1
  • rollupSize = 1024
  • numInnerRollups = 32

For the first slot visible to Layer 1:

  • proofId = 0 (empty transaction)
  • publicValue = 0

For slots 2–32, which Layer 1 could not see:

  • proofId = 1 (deposit transaction)
  • publicValue = N
  • publicOwner = attacker’s L2 address

Each rollup included valid ZK-proofs, and the verification circuit did not restrict publicValue to zero in the hidden slots.

The first intermediary contract called RollupProcessor.processRollup() five times for Rollups #13277–13281.

The verifier accepted every proof because the SHA256 hash covered all 32 slots. However, Layer 1 processed only the first slot and saw nothing but an empty operation.

The fake deposits hidden in slots 2–32 were added to the Merkle tree state root, increasing the attacker’s Layer 2 balance by 5 × 31N.

The second intermediary contract repeated the process for Rollups #13282–13283, adding another 2 × 31N.

By the end of Phase 1, the attacker had accumulated 7 × 31N in unbacked Layer 2 assets while the Layer 1 pool remained untouched.

Dozens of GnosisPay Wallets drained: A deep dive into a bold attack

Dozens of GnosisPay Wallets drained: A deep dive into a bold attack

The attacker didn’t hack the wallets directly. Instead, they tricked the security system into approving fraudulent transactions on its own. A flaw in the signature verification mechanism led to losses of approximately $265K.

Читать дальше

Phase 2: Converting Fake L2 Assets Into Real L1 Funds (Rollups #13284–13290)

Once the artificial balance was created, the attacker used seven withdrawal rollups to convert it into real assets.

Withdrawals included:

  • 270,513.054 DAI (Rollup #13284)
  • 167.890 wstETH (Rollup #13285)
  • 4,873.857 yvDAI (Rollup #13286)
  • 16.570 yvWETH (Rollup #13287)
  • 9,273.734 LUSD (Rollup #13288)
  • 359.047 yvLUSD (Rollup #13289)
  • 908.987 ETH (Rollup #13290)

The entire transaction consumed 4,513,539 gas and completed successfully. Because it was atomic, it could not be partially reversed.

The attacker ultimately withdrew approximately $2.2 million directly from assets managed by the RollupProcessor contract.

Tracking the Stolen Funds

Blockchain analysis conducted on June 15, 2026—roughly one day after the exploit—showed that all assets had been transferred from RollupProcessor to the attacker’s wallet (0x0F18D8b44a740272f0be4d08338d2b165b7EdD17) through an intermediary attack contract in a single transaction.

Flow of funds stolen from Aztec Connect. Source: MistTrack

No assets remained in the intermediary contract.

At the time of analysis, 100% of the stolen funds were still sitting in the attacker’s primary wallet, with no signs of laundering or further movement.

Key Lessons From the Incident

The most important takeaway is that, in ZK-rollup systems, the data range verified by the Layer 1 settlement contract must exactly match the data range authenticated by the cryptographic hash of public inputs.

If a gap appears between the numRealTxs processing boundary on Layer 1 and the decoded_slots range validated through SHA256, attackers can exploit the discrepancy.

Any security model that relies solely on constraints within the ZK circuit becomes vulnerable if those constraints fail.

Layer 1 contracts must independently validate every public data slot covered by a ZK-proof. Delegating this responsibility entirely to the proving system creates significant risk.

The exploit also highlights the danger of legacy smart contracts that continue holding user funds after a project has been shut down. Immutable contracts containing substantial assets can remain attractive targets for attackers years after development has ended.

Subscribe to Getblock Magazine and stay up to date with the latest news from the world of cryptocurrencies and the digital economy