Snowman Merkle Airdrop

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

Storage Variables Could Be Immutable

Root + Impact

Description

The Snow and Snowman contracts declare storage variables that are assigned only once during deployment (typically in the constructor) but are not marked as immutable.

In Solidity, variables that are set once during construction and never modified thereafter should be declared immutable. This not only provides clearer intent at the code level but also enables the compiler to optimize storage by embedding the value directly into the contract bytecode, significantly reducing gas costs on reads.

Failing to use immutable results in unnecessary storage reads during runtime, which are substantially more expensive than accessing an immutable variable.

Risk

Likelihood: Low
Impact: Low

This issue does not introduce any functional or security risk. However, it results in unnecessary gas inefficiencies on each read of the affected variables. Over time, especially in frequently accessed functions, these inefficiencies can compound. Furthermore, it reduces clarity in the code by not distinguishing between variables that are constant after deployment and those that are truly dynamic.

Proof of Concept

In the Snow contract:

contract Snow {
uint256 public s_buyFee; // Assigned once, never modified
IERC20 i_weth; // Likely intended to be immutable
}

In the Snowman contract:

contract Snowman {
string private s_SnowmanSvgUri; // Assigned once, never updated
}

These variables are initialized once during deployment but not updated afterward, making them prime candidates for the immutable modifier.

Recommended Mitigation

Refactor these variables to use the immutable keyword to reduce storage costs and improve code clarity. This allows the compiler to store the values in the contract's bytecode, making future accesses cheaper.

Suggested Fix — Snow Contract

contract Snow {
- uint256 public s_buyFee;
+ uint256 public immutable i_buyFee;
- IERC20 i_weth;
+ IERC20 immutable i_weth;
- s_buyFee = _buyFee * PRECISION;
+ i_buyFee = _buyFee * PRECISION;
- if (msg.value == (s_buyFee * amount)) {
+ if (msg.value == (i_buyFee * amount)) {
- i_weth.safeTransferFrom(msg.sender, address(this), (s_buyFee * amount));
+ i_weth.safeTransferFrom(msg.sender, address(this), (i_buyFee * amount));
}

Suggested Fix — Snowman Contract

contract Snowman {
- string private s_SnowmanSvgUri;
+ string private immutable i_SnowmanSvgUri;
- s_SnowmanSvgUri = _SnowmanSvgUri;
+ i_SnowmanSvgUri = _SnowmanSvgUri;
- string memory imageURI = s_SnowmanSvgUri;
+ string memory imageURI = i_SnowmanSvgUri;
}

Ensure these values are still properly initialized in the constructor. This change will reduce gas costs for every future access and signal the read-only nature of the values more clearly.

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.