Snowman Merkle Airdrop

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

[Informational] Centralization Risk in Snowman.sol Owner Functions - Hour 3

Summary

During Hour 3 of the Snowman First Flight, I conducted a manual review of access control patterns in Snowman.sol. The contract grants the owner unrestricted access to mint() and setOwner() functions. While no direct vulnerability was found, this presents a centralization risk if the owner key is compromised.

Vulnerability Details

Severity: Low - Informational
Contract: Snowman.sol
Functions: mint(address,uint256), setOwner(address)

Description

The current implementation allows the contract owner to mint new tokens at any time and transfer ownership instantly without delay. This is standard for many ERC20s, but creates risk. If the owner's private key is leaked or the owner acts maliciously, they can inflate supply or rug the contract. There are no timelocks, multisig requirements, or event emissions for transparency.

Impact

An attacker or compromised owner could:

  1. Mint unlimited tokens and dump them

  2. Transfer ownership to attacker wallet
    This damages user trust and token value.

Proof of Concept

// Current risky code
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount); // No cap, no delay
}
function setOwner(address newOwner) external onlyOwner {
owner = newOwner; // Instant transfer
}
// Attack scenario:
1. Owner private key is compromised
2. Attacker calls mint(attacker, 1e30)
3. Attacker dumps tokens
## Summary
Performed a 1-hour manual security review of the `Snowman.sol` contract during CodeHawks First Flight. Focus areas were access control, token minting logic, and owner privileges. No critical vulnerabilities were found. This submission documents a centralization risk.
## Vulnerability Details
**Severity:** Low - Informational
**Contract:** Snowman.sol
**Functions:** `mint(address,uint256)`, `setOwner(address)`
## Description
The contract allows the owner to call `mint()` with no cap and `setOwner()` with no delay. While `onlyOwner` is present, there is no timelock, multisig, or event emission. If the owner private key is compromised, an attacker could mint unlimited tokens or transfer ownership instantly. This is a common pattern but considered a best practice issue.
## Impact
If exploited:
1. Attacker mints unlimited supply and dumps
2. Attacker takes ownership and rugs the contract
This leads to loss of user funds and trust.
## Proof of Concept
```solidity
// Current implementation
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
function setOwner(address newOwner) external onlyOwner {
owner = newOwner;
}
// Scenario: Owner key leaked -> attacker calls mint(attacker, type(uint256).max
import "@openzeppelin/contracts/access/Ownable2Step.sol";
contract Snowman is Ownable2Step {
uint256 public constant TIMELOCK = 2 days;
uint256 public pendingOwnerTime;
address public pendingOwner;
event TokensMinted(address indexed to, uint256 amount);
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
emit TokensMinted(to, amount);
}
function transferOwnership(address newOwner) public override onlyOwner {
pendingOwner = newOwner;
pendingOwnerTime = block.timestamp + TIMELOCK;
}
}
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!