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
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
The claim() function derives the leaf from the caller-supplied account parameter:
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.
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:
Alternatively, add an EIP-712 signed message verification so users can prove ownership of both their L1 and L2 addresses.
## 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.
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.