Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Unrestricted Proof Reuse Allows Multiple Airdrop Claims

Summary

The MerkleAirdrop contract is vulnerable to an attack where a user can claim their airdrop tokens multiple times due to the lack of a tracking mechanism for claimed statuses.

Vulnerability Details

The contract's claim function does not record whether an airdrop has been claimed by a particular account, allowing the same merkle proof to be used repeatedly to withdraw tokens.

Impact

This vulnerability could lead to the depletion of all airdrop tokens by a single or multiple attackers, resulting in financial loss and a compromised airdrop distribution.

Tools Used

Manual Code Review

Proof Of Code

function claim(address account, uint256 amount, bytes32[] calldata merkleProof) external payable {
if (msg.value != FEE) {
revert MerkleAirdrop__InvalidFeeAmount();
}
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount))));
if (!MerkleProof.verify(merkleProof, i_merkleRoot, leaf)) {
revert MerkleAirdrop__InvalidProof();
}
emit Claimed(account, amount);
i_airdropToken.safeTransfer(account, amount);
}

Recommendations

To mitigate this issue, implement a mapping to track whether an account has claimed its airdrop and update the claim function to check this mapping:

mapping(address => bool) private hasClaimed;
function claim(address account, uint256 amount, bytes32[] calldata merkleProof) external payable {
require(!hasClaimed[account], "MerkleAirdrop: Tokens already claimed.");
// ... existing checks ...
hasClaimed[account] = true;
emit Claimed(account, amount);
i_airdropToken.safeTransfer(account, amount);
}

This change ensures that once an account has claimed its tokens, any subsequent attempts to claim using the same account and merkle proof will fail. Additionally, introduce a custom error for a more gas-efficient way of handling the already claimed scenario:

error MerkleAirdrop__AlreadyClaimed();
// Inside the claim function
if (hasClaimed[account]) {
revert MerkleAirdrop__AlreadyClaimed();
}

By implementing this mapping and check, the contract will be protected against the repeated claim vulnerability, preserving the integrity of the airdrop process and ensuring that tokens are distributed as intended.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

multi-claim-airdrop

Support

FAQs

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