All incidents

FOOM Lottery verifier parameter collapse enables arbitrary collect drains

Share
Feb 26, 2026 07:23 UTCAttackLoss: 19,695,576,757,802.19 FOOM, 4,588,196,709,631.8 FOOMManually checked2 exploit txWindow: 15m 58s
Estimated Impact
19,695,576,757,802.19 FOOM, 4,588,196,709,631.8 FOOM
Label
Attack
Exploit Tx
2
Addresses
2
Attack Window
15m 58s
Feb 26, 2026 07:23 UTC → Feb 26, 2026 07:39 UTC

Exploit Transactions

TX 1Ethereum
0xce20448233f5ea6b6d7209cc40b4dc27b65e07728f2cbbfeb29fc0814e275e48
Feb 26, 2026 07:39 UTCExplorer
TX 2Base
0xa88317a105155b464118431ce1073d272d8b43e87aba528a24b62075e48d929d
Feb 26, 2026 07:23 UTCExplorer

Victim Addresses

0x239af915abcd0a5dcb8566e863088423831951f8Ethereum
0xdb203504ba1fea79164af3ceffba88c59ee8aafdBase

Loss Breakdown

19,695,576,757,802.19FOOM
4,588,196,709,631.8FOOM

Similar Incidents

Root Cause Analysis

FOOM Lottery verifier parameter collapse enables arbitrary collect drains

1. Incident Overview TL;DR

Two seed transactions on Ethereum and Base drained FOOM from FOOM Lottery contracts by forging withdraw proofs and repeatedly calling collect.

  • Ethereum seed tx: 0xce20448233f5ea6b6d7209cc40b4dc27b65e07728f2cbbfeb29fc0814e275e48 (block 24539650)
  • Base seed tx: 0xa88317a105155b464118431ce1073d272d8b43e87aba528a24b62075e48d929d (block 42650623)

The root cause is malformed Groth16 verifier constants in WithdrawG16Verifier: delta is set equal to gamma. This removes soundness for the intended statement and allows attacker-computed proofs for attacker-chosen public signals. FoomLottery.collect trusts withdraw.verifyProof(...) and computes payout directly from attacker-supplied rewardbits, so forged proofs become direct token outflows.

2. Key Background

FOOM Lottery payout redemption path requires a Groth16 proof through withdraw.verifyProof(...) and uses public signals:

  • _root
  • _nullifierHash
  • _rewardbits
  • recipient/relayer/fee/refund fields

The contract requires:

  • unused nullifier,
  • known Merkle root,
  • verifier acceptance,

then transfers FOOM reward to recipient.

Groth16 verifier correctness requires independent gamma and delta terms in the pairing equation. If delta == gamma, adversarial construction with verifier constants (A=alpha, B=beta, C=-vk_x) satisfies the pairing equation for arbitrary valid-field public signals.

3. Vulnerability Analysis & Root Cause Summary

This is an ATTACK-class vulnerability in verifier parameterization and downstream trust of verifier output in a high-value payout path. The verifier constants on both chains hardcode identical points for gamma and delta. That collapse allows forged proof acceptance without a legitimate witness tied to an actual winning ticket statement. The lottery redemption function then accepts attacker-selected rewardbits, nullifier, and recipient once verifier returns true. The exploit therefore does not require privileged roles or private keys and is executable by an unprivileged actor using normal on-chain calls. Deterministic trace evidence shows repeated successful collect calls in one transaction per chain and matching FOOM balance transfers from lottery to attacker EOAs.

Representative verifier constant evidence (Ethereum verifier source):

uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;

4. Detailed Root Cause Analysis

4.1 Invariant and breakpoint

Safety invariant:

  • only a valid witness for the intended withdrawal statement should satisfy verifyProof for supplied public signals.

Code-level breakpoint:

  • WithdrawG16Verifier hardcodes delta == gamma.
  • FoomLottery.collect uses verifier result as the decisive gate and computes reward directly from _rewardbits.

Representative redemption logic (Ethereum lottery source):

require(nullifier[_nullifierHash] == 0, "Incorrect nullifier");
nullifier[_nullifierHash] = 1;
uint reward = uint(betMin) * (
    (_rewardbits & 0x1 > 0 ? 1 : 0) * 2**betPower1 +
    (_rewardbits & 0x2 > 0 ? 1 : 0) * 2**betPower2 +
    (_rewardbits & 0x4 > 0 ? 1 : 0) * 2**betPower3
);
require(roots[_root] > 0, "Cannot find your merkle root");
require(withdraw.verifyProof(_pA, _pB, _pC, [
    _root, _nullifierHash, _rewardbits, uint(uint160(_recipient)),
    uint(uint160(_relayer)), _fee, _refund
]), "Invalid withdraw proof");

4.2 On-chain execution evidence

Ethereum trace shows repeated forged redemption pattern:

FoomLottery::collect(... rewardbits=7 ...)
WithdrawG16Verifier::verifyProof(...) [staticcall]
emit LogWin(... recipient: 0x46c403e3DcAF219D9D4De167cCc4e0dd8E81Eb72)

Base trace shows the same pattern:

0xdb203504ba1fea79164AF3CeFFBA88C59Ee8aAfD::collect(... rewardbits=7 ...)
0x02c30D32A92a3C338bc43b78933D293dED4f68C6::verifyProof(...) [staticcall]
emit LogWin(... param2: 0x73f55A95D6959D95B3f3f11dDd268ec502dAB1Ea)

Observed call counts from trace logs:

  • Ethereum seed tx: 30 LogWin emissions
  • Base seed tx: 10 LogWin emissions

4.3 ACT exploit conditions

The exploit requires only:

  • existing root in roots mapping,
  • FOOM balance available in lottery,
  • unused nullifier values,
  • unprivileged transaction submission.

These conditions are publicly observable and permissionless.

5. Adversary Flow Analysis

Adversary-related accounts in seed flow:

  • Ethereum EOA: 0x46c403e3dcaf219d9d4de167ccc4e0dd8e81eb72
  • Ethereum helper contract: 0x256a5d6852fa5b3c55d3b132e3669a0bde42e22c
  • Base EOA: 0x73f55a95d6959d95b3f3f11ddd268ec502dab1ea
  • Base helper contract: 0x005299b37703511b35d851e17dd8d4615e8a2c9b

Execution sequence per chain:

  1. EOA deploys one-shot helper contract.
  2. Helper constructs forged proof components on-chain.
  3. Helper calls collect repeatedly with unique nullifiers and rewardbits=7.
  4. Verifier accepts forged proofs.
  5. Lottery transfers FOOM to attacker EOA.

This sequence is permissionless, reproducible on canonical state, and matches ACT criteria.

6. Impact & Losses

Deterministic balance diffs show:

  • Ethereum lottery (0x239af915abcd0a5dcb8566e863088423831951f8) lost 19695576757802192910518134117126 FOOM.
  • Base lottery (0xdb203504ba1fea79164af3ceffba88c59ee8aafd) lost 4588196709631799956807157941481 FOOM.
  • Corresponding attacker EOAs gained exactly those amounts.

Representative balance-diff evidence:

{
  "token": "0xd0d56273290d339aaf1417d9bfa1bb8cfe8a0933",
  "holder": "0x46c403e3dcaf219d9d4de167ccc4e0dd8e81eb72",
  "delta": "19695576757802192910518134117126"
}
{
  "token": "0x02300ac24838570012027e0a90d3feccef3c51d2",
  "holder": "0x73f55a95d6959d95b3f3f11ddd268ec502dab1ea",
  "delta": "4588196709631799956807157941481"
}

FOOM-denominated fee treatment is deterministic:

  • reference asset: FOOM
  • exploit gas fees are paid in native ETH
  • therefore fees_paid_in_reference_asset = 0

Receipt-backed native gas fees:

  • Ethereum seed tx fee: 423890852910344 wei
  • Base seed tx fee: 19644923790540 wei

7. References

  • Ethereum seed tx trace: 0xce20448233f5ea6b6d7209cc40b4dc27b65e07728f2cbbfeb29fc0814e275e48
  • Base seed tx trace: 0xa88317a105155b464118431ce1073d272d8b43e87aba528a24b62075e48d929d
  • Ethereum verifier: 0xc043865fb4d542e2bc5ed5ed9a2f0939965671a6 (WithdrawG16Verifier.verifyProof)
  • Base verifier: 0x02c30d32a92a3c338bc43b78933d293ded4f68c6 (WithdrawG16Verifier.verifyProof)
  • Ethereum lottery: 0x239af915abcd0a5dcb8566e863088423831951f8 (FoomLottery.collect)
  • Base lottery: 0xdb203504ba1fea79164af3ceffba88c59ee8aafd (FoomLottery.collect)
  • Ethereum balance diff artifact for seed tx
  • Base balance diff artifact for seed tx
  • Deterministic fee summary: /workspace/session/artifacts/auditor/iter_2/tx_fee_summary.json