AirDropper

AI First Flight #5
Beginner FriendlyDeFiFoundry
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Anyone can call the `MerkleAirdrop::claim` function on an address that is on the reward lists.

Anyone can call the MerkleAirdrop::claim function on an address that is on the reward lists.

Description

Any address not on the reward list can call MerkleAirdrop::claim. There is no check to see if the caller's address matches the one they pass in the parameters when calling.

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

Risk

An attacker can call a function from his address that is not whitelisted for receiving the reward and drain the entire balance of 100 USDC to the address that is. Thereby spoiling the concept of the entire protocol, which should receive the reward of four different addresses. The user who will call the function will not understand why I will get an error.


Proof of Concept

  1. We create the address of the attacker from which the claim will be triggered.

  2. We give him funds to pay the commission.

  3. We trigger the claim from the attacker by inserting the address of the user who has the right to use it.

  4. The attacker, having funds to pay the commission, can receive funds for them for everyone.

function testClaimFromSecondPerson() public {
address secondPerson = makeAddr("secondPerson");
vm.deal(secondPerson, airdrop.getFee());
vm.startPrank(secondPerson);
airdrop.claim{value: airdrop.getFee()}(
collectorOne,
amountToCollect,
proof
);
vm.stopPrank();
uint256 endBalance = token.balanceOf(collectorOne);
assertEq(endBalance, 25 * 1e6);
}

Recommended Mitigation

No caller validation, need to check if caller matches address passed in function parameters.

Add error for better user experience.


+ error MerkleAirdrop__InvalidSender();
// your code here
function claim(
address account,
uint256 amount,
bytes32[] calldata merkleProof
) external payable {
+ if(account != msg.sender) {
+ revert MerkleAirdrop__InvalidSender();
}
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);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 11 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!