Summary
The claim function in the MerkleAirdrop contract lacks validation of the address sending the transaction. This oversight allows any party to submit the merkle proof of a user who does not wish to receive the airdrop, potentially leading to unauthorized claims.
Impact
This vulnerability enables anyone to force the claim of the airdrop tokens.
Proof of Concept:
To demonstrate the issue, add the following code to the existing MerkleAirdropTest contract:
Proof Of Code
function testAnyoneCanForceClaim() public {
uint256 startingBalance = token.balanceOf(collectorOne);
address forcer = makeAddr("forcer");
vm.deal(forcer, airdrop.getFee());
vm.startPrank(forcer);
airdrop.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
vm.stopPrank();
uint256 endingBalance = token.balanceOf(collectorOne);
assertEq(endingBalance - startingBalance, amountToCollect);
}
Tools Used
foudnry
Recommendations
In the MerkleAirdrop::claim function, validate that the sender is the intended receiver of the airdrop tokens.
function claim(address account, uint256 amount, bytes32[] calldata merkleProof) external payable {
+ if (msg.sender != account) {
+ revert();
+ }
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);
}