Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Lack of Emission Control/Rate Limiting (Minting Abuse Potential) in `Snowman.sol`

[L-3] Lack of Emission Control/Rate Limiting (Minting Abuse Potential) in Snowman.sol


Description

Even assuming that appropriate access control (as recommended in [H-3]) is implemented for the mintSnowman function, the contract currently lacks any further mechanisms to control the rate or frequency at which NFTs can be minted. There are no daily quotas, per-wallet mint limits within a specific timeframe, or other throttling mechanisms in place.


Risk

While access control prevents unauthorized parties from minting, an authorized address (e.g., the contract owner or an admin) could still mass-mint an excessive number of NFTs in a single transaction or through rapid, repeated calls. This can lead to:
1. Resource Spikes: Large minting events can cause significant gas usage spikes, potentially leading to network congestion and higher transaction fees during peak times.
2. Uncontrolled Distribution: Without emission controls, it becomes challenging to manage the gradual distribution or supply of tokens over time. This can hinder long-term project planning, community building, or value appreciation strategies (e.g., absence of vesting or drip mechanisms).
3. Abuse by Authorized Party/Compromise: If an admin key were compromised, or even due to negligence from the owner, an extremely large number of tokens could be minted very quickly, potentially devaluing the collection or causing market instability.


Proof Of Concept

function mintSnowman(address receiver, uint256 amount) external onlyOwner {
for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, nextTokenId++);
}
}

**Malicious scenario : **

A privileged user (or attacker with compromised key) executes:

// Single transaction with massive mint amount
snowman.mintSnowman(admin, 100_000); // No per-tx cap
// Or repeated rapid calls
for (uint256 i = 0; i < 200; i++) {
snowman.mintSnowman(admin, 500); // Total: 100,000 NFTs minted
}

Recommended Mitigation

Introduce specific rate-limiting or emission control mechanisms into the mintSnowman function, tailored to the project's economic goals, distribution strategy, and desired level of decentralization. Common approaches include:
* Per-Transaction Limit: Restrict the amount parameter to a reasonable maximum number of NFTs that can be minted in a single call.
* Per-Wallet/Global Daily/Weekly Limits: Implement mappings (mapping(address => uint256) public s_mintsPerDay;) and/or global counters to track and limit minting activity over specific time periods, resetting periodically.
* Timestamp-Based Throttling: Use block.timestamp to enforce cooldowns between minting operations for specific addresses or globally.
* Tiered Access/Vesting: For more complex distribution, consider tiered access or vesting schedules.

Example (combining with [H-3] and [H-5] mitigations):

// Example additions in Snowman.sol
uint256 public constant MAX_MINTS_PER_TX = 100; // Example: Max 100 NFTs per single mint call
mapping(address => uint256) private s_lastDailyMintTime;
mapping(address => uint256) private s_dailyMintsCount; // Tracks daily mints per address
uint256 public constant DAILY_MINT_LIMIT_PER_ADDRESS = 500; // Example: Max 500 NFTs per user per day
function mintSnowman(address receiver, uint256 amount) external onlyOwner supplyCheck(amount) {
// Enforce a limit on the number of NFTs that can be minted in one transaction
require(amount <= MAX_MINTS_PER_TX, "Snowman: Amount exceeds per-transaction mint limit");
// Enforce a daily mint limit per recipient address
if (block.timestamp / 1 days > s_lastDailyMintTime[receiver] / 1 days) {
s_dailyMintsCount[receiver] = 0; // Reset daily count for a new day
}
require(s_dailyMintsCount[receiver] + amount <= DAILY_MINT_LIMIT_PER_ADDRESS, "Snowman: Exceeds daily mint limit for this address");
s_dailyMintsCount[receiver] += amount;
s_lastDailyMintTime[receiver] = block.timestamp;
// ... rest of original minting logic ...
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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