# Improper Access Control on `mintSnowma` allows Unrestricted Minting
## Description
* Normally, a `mint` function in an NFT contract should include **access control** to restrict who is allowed to mint tokens. This ensures only trusted contracts or parties can issue new NFTs.
* In the current implementation of the `Snowman` contract, the `mintSnowman` function is marked `external` and has **no access control**, meaning **any external address** can mint unlimited NFTs.
```solidity
function mintSnowman(address receiver, uint256 amount) external {
@> // No access control – anyone can call this
for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, s_TokenCounter);
s_TokenCounter++;
}
}
```
## Risk
**Likelihood**:
* This will occur whenever a malicious actor directly calls `mintSnowman()` to mint unauthorized NFTs.
**Impact**:
* Anyone can arbitrarily inflate the Snowman NFT supply.
* Completely breaks the trust model and devalues legitimately claimed NFTs.
## Proof of Concept
The following solidity example shows that anyone can call mintSnowman function and claim NFT's.
```solidity
Snowman snowman = Snowman(SNOWMAN_ADDRESS);
// Malicious user calls mint directly
snowman.mintSnowman(msg.sender, 1000); // mints 1000 fake NFTs
```
## Recommended Mitigation
Restrict access to `mintSnowman` so only the `SnowmanAirdrop` contract can call it. Use a one-time setter or constructor injection pattern. Also `i_airdrop` represents address of Snowman Airdrop contract so only via Snowman Airdrop contract Snowman NFT's can be minted.
```diff
+ address private immutable i_airdrop;
- constructor(string memory _SnowmanSvgUri) ERC721("Snowman Airdrop", "SNOWMAN") Ownable(msg.sender) {
+ constructor(string memory _SnowmanSvgUri, address airdrop) ERC721("Snowman Airdrop", "SNOWMAN") Ownable(msg.sender) {
+ require(airdrop != address(0), "Invalid airdrop address");
+ i_airdrop = airdrop;
s_TokenCounter = 0;
s_SnowmanSvgUri = _SnowmanSvgUri;
}
function mintSnowman(address receiver, uint256 amount) external {
+ if (msg.sender != i_airdrop) {
+ revert SM__NotAllowed();
+ }
for (uint256 i = 0; i < amount; i++) {
_safeMint(receiver, s_TokenCounter);
s_TokenCounter++;
}
}
```
This ensures only the trusted `SnowmanAirdrop` contract can call `mintSnowman()` while preventing any external abuse.