AirDropper

AI First Flight #5
Beginner FriendlyDeFiFoundry
EXP
View results
Submission Details
Severity: high
Valid

Users with account abstraction wallets cannot claim due to cross-chain address mismatch

Description

  • Normal: The whitelist uses Ethereum L1 addresses. Users on zkSync Era should be able to claim with their corresponding zkSync address.

  • Bug: Account abstraction (AA) wallets have different addresses on different chains for the same account. The whitelist uses Ethereum L1 addresses, but the contract is deployed on zkSync Era. If any of the 4 lucky users uses an AA wallet (e.g., Safe, Argent), their zkSync address differs from their Ethereum address — the Merkle proof will not match and they cannot claim.

The project documentation states:

"Our team is looking to airdrop 100 USDC tokens on the zkSync era chain to 4 lucky addresses based on their activity on the Ethereum L1."

The whitelisted addresses are Ethereum L1 addresses:

  • 0x20F41376c713072937eb02Be70ee1eD0D639966C

  • 0x277D26a45Add5775F21256159F089769892CEa5B

  • 0x0c8Ca207e27a1a8224D1b602bf856479b03319e7

  • 0xf6dBa02C01AF48Cf926579F77C9f874Ca640D91D

Risk

Likelihood:

  • Account abstraction wallets (Safe, Argent, Biconomy) are widely used by active DeFi users

  • Given 4 whitelisted addresses, the probability at least one uses an AA wallet is non-trivial

  • No fallback mechanism exists for users with mismatched addresses

Impact:

  • Affected users permanently lose their airdrop allocation

  • Funds remain locked in the contract with no claimant

  • Protocol fails its stated goal of distributing tokens to the intended Ethereum users

Proof of Concept

The claim() function derives the leaf from the caller-supplied account parameter:

bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount))));

The Merkle tree was built with Ethereum L1 addresses. An AA wallet user on zkSync has a different address — their keccak256(abi.encode(zkSyncAddress, amount)) produces a different leaf than the one in the tree. The Merkle proof verification fails even though they are the same person.

Recommended Mitigation

Before generating the Merkle tree, verify each user's zkSync Era address (not just their Ethereum L1 address). Update makeMerkle.js to use zkSync addresses:

const values = [
- ["0x20F41376c713072937eb02Be70ee1eD0D639966C", amount],
+ ["<zkSync address for user 1>", amount],
// ... for all 4 users
];

Alternatively, add an EIP-712 signed message verification so users can prove ownership of both their L1 and L2 addresses.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 11 hours ago
Submission Judgement Published
Validated
Assigned finding tags:

[H-04] Unable to receive airdrop due to account abstraction

## Description The users that use account abstraction wallets have different addresses across chains for the same account. ## Vulnerability Details In the docs is said: ```javascript "Our team is looking to airdrop 100 USDC tokens on the zkSync era chain to 4 lucky addresses based on their activity on the Ethereum L1. The Ethereum addresses are: 0x20F41376c713072937eb02Be70ee1eD0D639966C 0x277D26a45Add5775F21256159F089769892CEa5B 0x0c8Ca207e27a1a8224D1b602bf856479b03319e7 0xf6dBa02C01AF48Cf926579F77C9f874Ca640D91D" ``` The user can claim his/her USDC tokens through the `MerkleAirdrop::claim` function. This function requires `account, amount and proof array`. With the help of this three arguments the merkle proof will ensure that the caller is eligible to claim. But in the generated merkle root are used the Ethereum addresses of the lucky users. But the protocol will be deployed on the zkSync era chain. If any of them uses account abstraction wallet, this lucky user will not be able to claim his/her tokens. The account abstraction wallets have different addresses in the different chains for the same account. ## Impact The users that use account abstraction wallets have different addresses on the zkSync era chain. That means these users will not be able to claim their USDC tokens, because the merkle root will require another account address (this on Ethereum). ## Recommendations Ensure that the addresses in `makeMerkle` file for the lucky users are their addresses for the zkSync era chain.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!