AirDropper

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

Unused MerkleRootUpdated event is dead code

Description

MerkleAirdrop declares two events. Claimed is emitted on every successful claim. MerkleRootUpdated is declared but never emitted anywhere in the contract:

// src/MerkleAirdrop.sol, line 19-20
event Claimed(address account, uint256 amount);
event MerkleRootUpdated(bytes32 newMerkleRoot); // @> declared but never emitted

The merkle root is stored as immutable (line 17), so no function can update it after deployment. The event name implies a root update mechanism was planned but never implemented. This is dead code copied from a template without cleanup.

// src/MerkleAirdrop.sol, line 17
bytes32 private immutable i_merkleRoot; // @> immutable — cannot be updated post-deployment

The contract has no setMerkleRoot() or equivalent function. The event exists only in the ABI and bytecode, serving no purpose.

Risk

Likelihood:

  • The dead event is always present in every deployment. Any tooling or frontend parsing the ABI will see MerkleRootUpdated and expect a root update mechanism.

  • Integrators building monitoring or indexing systems will set up listeners for an event that never fires.

Impact:

  • Misleads integrators into expecting root update functionality that does not exist. Monitoring dashboards tracking MerkleRootUpdated provide false confidence that root changes are observable.

  • Marginal gas overhead on deployment from unused bytecode.

Proof of Concept

function testDeadEvent_MerkleRootUpdated() public view {
// The event is declared in the ABI but grep the entire contract:
// "MerkleRootUpdated" appears ONLY in the event declaration (line 20)
// It is never emitted in claim(), claimFees(), constructor, or any other function
//
// Meanwhile i_merkleRoot is immutable:
bytes32 root = airdrop.getMerkleRoot();
assert(root != bytes32(0)); // root is set once in constructor, never changes
// There is no setMerkleRoot() function — the event can never fire
}

A simple grep confirms the event is never emitted:

$ grep -n "MerkleRootUpdated" src/MerkleAirdrop.sol
20: event MerkleRootUpdated(bytes32 newMerkleRoot);
// Only the declaration — zero emit statements

Recommended Mitigation

Remove the unused event to reduce ABI surface and avoid misleading integrators:

event Claimed(address account, uint256 amount);
- event MerkleRootUpdated(bytes32 newMerkleRoot);

If root updates are a desired future feature, i_merkleRoot must be changed from immutable to a regular state variable with an onlyOwner setter that emits the event.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 17 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!