Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

[Informational] Gas Optimization: Use ++i Instead of i++ in Loops - Snowman.sol

Summary

During Hour 5 of Snowman First Flight, I performed a gas optimization review of Snowman.sol. Found several places using i++ in for-loops and unnecessary storage reads. These are not vulnerabilities but increase gas costs for users. No security issues found.

Vulnerability Details

Severity: Low - Informational / Gas Optimization
Contract: Snowman.sol
Category: Gas

Risk

Higher gas costs for users. Over time with many transactions this wastes ETH. Does not affect security or functionality.

Description

Solidity uses more gas for post-increment i++ vs pre-increment ++i in for-loops because i++ creates a temporary copy. Also, reading state variables multiple times inside loops instead of caching to memory costs extra SLOADs ~100 gas each.

Proof of Concept

// Inefficient pattern found
function batchMint(address[] calldata recipients, uint256 amount) external onlyOwner {
for(uint256 i = 0; i < recipients.length; i++) { // i++ uses more gas
_mint(recipients[i], amount);
require(balanceOf(recipients[i]) > 0, "Failed"); // SLOAD every loop
}
}
// Gas wasted per loop:
// 1. i++ instead of ++i = ~5 gas
// 2. balanceOf() SLOAD = ~100 gas
function batchMint(address[] calldata recipients, uint256 amount) external onlyOwner {
uint256 len = recipients.length; // Cache length - saves gas
for(uint256 i = 0; i < len; ++i) { // ++i is cheaper
address recipient = recipients[i]; // Cache array read
_mint(recipient, amount);
uint256 bal = balanceOf(recipient); // Cache if used multiple times
require(bal > 0, "Failed");
}
}
## Summary
During my security review of `Snowman.sol`, I reviewed all state-changing functions. I found that `mint()` and `setOwner()` do not emit custom events. While `_mint()` emits Transfer, there is no specific event for tracking mints or ownership changes. This reduces transparency for users and monitoring tools.
## Vulnerability Details
**Severity:** Low - Informational
**Contract:** Snowman.sol
**Functions Affected:** `mint(address,uint256)`, `setOwner(address)`
## Risk
1. Dapps and indexers cannot distinguish between normal transfers and owner mints
2. No way to monitor ownership changes without parsing raw transactions
3. Reduces transparency and makes incident response harder
No direct loss of funds, but impacts UX and security monitoring.
## Description
Best practice per EIP-20 and OpenZeppelin is to emit events for all significant state changes. The current implementation relies only on the default Transfer event from `_mint()`. For admin functions like `mint()` and `setOwner()`, custom events should be added.
## Proof of Concept
```solidity
// Current implementation
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount); // Only emits Transfer(to, amount)
}
function setOwner(address newOwner) external onlyOwner {
owner = newOwner; // No event at all
}
// Issue: Off-chain services cannot tell this was an admin mint vs user transfer
// Issue: No event to track when owner changed
Updates

Lead Judging Commences

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