How a zk verification flaw triggered the FoomCash $1.6M exploit. In-depth breakdown of the attack, root cause, impact and key security lessons.

FoomCash suffered a critical zk-verification failure that resulted in approximately $1.3M+ in FOOM tokens being drained on Ethereum, with an additional $316K compromised on Base. The exploit did not involve reentrancy, flash loans, or complex DeFi mechanics. Instead, it stemmed from a fundamental misconfiguration in the deployed Groth16 verifier contract. Specifically, two verification key constants (gamma and delta) were incorrectly set to identical elliptic curve points, breaking the soundness guarantees of the zk proof system. This flaw enabled the attacker to algebraically forge valid proofs and repeatedly withdraw funds without possessing any legitimate deposits or private witness.
The attacker performed the computation off-chain by deriving:

Since all parameters supplied to the collect() function were attacker-controlled, the attacker only needed to modify _nullifierHash to generate a new set of valid public inputs. Each change to _nullifierHash resulted in a new vk_x, after which the attacker recomputed:

By repeating this process, the attacker was able to generate fresh forged proof parameters for multiple calls to collect(), successfully bypassing verification on each iteration.

The attacker deployed a helper contract to automate repeated calls to the collect() function, constructing each invocation by incrementing _nullifierHashand recomputing the corresponding forged proof parameters.



Through repeated forged proof submissions, the attacker drained approximately $1.3M worth of FOOM tokens on Ethereum and replicated the same attack on Base, compromising an additional $316K worth of FOOM tokens.


Below is a simplified attack flow demonstrating how the zk verifier misconfiguration led to systematic fund extraction.

The exploit was caused by a critical misconfiguration in the deployed Groth16 verifier contract (0xc043865fb4D542E2bc5ed5Ed9A2F0939965671A6). Specifically, the verification key constants gamma and delta were set to identical elliptic curve points (gamma == delta). In Groth16, these two constants must be different to preserve proof soundness. Their equality collapses the mathematical separation between public input validation and witness validation.
A single misconfigured verification key can break proof soundness and enable forgery. Secure your Groth16, PLONK or custom zk circuits with a dedicated cryptographic audit.

Groth16 verification checks the pairing equation:

Where:
e() - A bilinear pairing over the BN254 elliptic curve (Ethereum precompile 0x08). It maps two curve points into a target group and allows cryptographic equality checks.A, B, C - Elements of the zk proof provided by the prover.alpha, beta - Fixed constants embedded in the verification key.vk_x - A linear combination of verification key input coefficients (IC points) weighted by the public inputs.gamma - Constant used to bind the proof to the public inputs.delta - Constant used to bind the proof to the private witness.The term vk_x is computed as:

Here, pub_i are public inputs such as the Merkle root, nullifier, recipient address, fee, etc. These values are fully attacker-controlled.
In a correctly configured verifier, gamma and delta are different curve points. This ensures that:
e(vk_x, gamma) enforces correct public input binding.e(C, delta) enforces correct witness binding.Because these two terms are paired against different constants, they cannot algebraically cancel each other.
However, in the deployed verifier, gamma == delta. This collapses the equation to:

This simplifies the verification condition to:

Which implies:

Since vk_xdepends only on public inputs, an attacker can compute it directly without knowing any private witness. They can then set:

Reuse the public constants alpha and beta for (A, B) and satisfy the pairing equation purely through algebraic cancellation. This completely breaks the soundness property of Groth16, enabling arbitrary proof forgery.
The forged proof can be verified directly on Ethereum mainnet.
Foundry is required to execute the following command.
1cast call 0xc043865fb4D542E2bc5ed5Ed9A2F0939965671A6 \
2"verifyProof(uint256[2],uint256[2][2],uint256[2],uint256[7])(bool)" \
3"[16428432848801857252194528405604668803277877773566238944394625302971855135431,16846502678714586896801519656441059708016666274385668027902869494772365009666]" \
4"[[3182164110458002340215786955198810119980427837186618912744689678939861918171,16348171800823588416173124589066524623406261996681292662100840445103873053252],[4920802715848186258981584729175884379674325733638798907835771393452862684714,19687132236965066906216944365591810874384658708175106803089633851114028275753]]" \
5"[3580187279101084069751145503379205138644462599730770566826054966809782222536,9034737010478553175860989655199489479494794665577903575343123912300687026525]" \
6"[7781146065974985251383064797749046122697630175951491630464801665880519130734,99999990000,7,404000638890875347995779038680777447236549340018,0,0,0]" \
7--rpc-url https://eth.llamarpc.comExpected output:
1trueRunning this command demonstrates that a forged proof constructed using only public inputs is accepted by the verifier.
On Ethereum, the FOOM tokens were swapped for USDT, seemingly at discounted prices.

The FOOM tokens on Base were bridged to Ethereum through Foom’s official bridge contract (0x2f534ce6843e7a773fd9f2e45d04e8608b9de3f8).

On Ethereum, the bridged tokens were subsequently converted into WETH.

At the time of writing, the converted FOOM (into USDT and ETH) remains sitting in the attacker’s EOAs.


FoomCash appears to have been inactive since November 2025, with no activity from either the FoomCash or FoomClub accounts. Additionally, the team has not released any official updates regarding the hack.
The FoomCash exploit highlights how a single cryptographic misconfiguration can completely undermine protocol security. By deploying a Groth16 verifier with gamma == delta, the protocol unintentionally eliminated proof soundness, enabling deterministic proof forgery. The attacker exploited this flaw systematically, draining funds across multiple chains. This incident underscores the importance of rigorous verification key validation, cryptographic audits, and invariant testing for zk-based systems before deployment.
Contents


From day-zero risk mapping to exchange-ready audits — QuillAudits helps projects grow with confidence. Smart contracts, dApps, infrastructure, compliance — secured end-to-end.