MerkleAirdrop.claimFees() collects all ETH held by the contract and forwards it to owner() using a low-level .call{value: balance}(""). If the call reverts, the function reverts with MerkleAirdrop__TransferFailed() — and the ETH stays in the contract.
On zkSync Era, native Account Abstraction means deployers are frequently smart contract accounts (multisigs, AA wallets, deployer scripts). Many of these do not implement receive() or fallback() with payable. If owner() is any such contract, every call to claimFees() will revert, and the accumulated ETH fee balance is permanently unreachable — the contract holds it with no alternative withdrawal path.
Likelihood:
zkSync Era natively encourages smart contract accounts. A deployer script, Gnosis Safe, or any AA wallet without a receive() function will trigger this bug on every claimFees() call.
Even on standard EVM chains, multisig owners that reject raw ETH are common.
Impact:
All ETH accumulated from claim fees is permanently locked. For an airdrop with many recipients (e.g., 1,000 claims at 1 gwei each = 1,000 gwei), the loss scales linearly.
The owner cannot recover the ETH short of a full contract redeployment (which also requires a new Merkle root and token refund).
The test deploys a NonPayableOwner contract as the owner of the airdrop. Alice claims and pays the fee. When claimFees() is called, the low-level ETH transfer to the non-payable owner reverts, locking the fee permanently in the airdrop contract.
The fee paid by Alice cannot be retrieved. With many claimants the trapped balance scales proportionally, and there is no rescue function.
Accept an explicit to address in claimFees() so the owner can direct ETH to a known-payable recipient:
This lets the owner specify an EOA or any contract known to accept ETH, avoiding permanent lockup regardless of what type of account holds ownership.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.