mintSnowman
Loop Can Lead to DoS for Large Mint AmountsProtocol Behavior: The SnowmanAirdrop.sol
contract is intended to call Snowman.sol::mintSnowman(receiver, amount)
where amount
is "equal to their Snow
balance" which the recipient staked.
Specific Issue: The mintSnowman
function in Snowman.sol
uses a for
loop to mint NFTs one by one: for (uint256 i = 0; i < amount; i++)
. The gas cost of this function call will therefore scale linearly with the amount
parameter. If a recipient has a very large Snow
balance and is entitled to a correspondingly large number of Snowman NFTs, the amount
can be substantial. Minting a large number of NFTs in a single transaction via this loop could consume gas exceeding the block gas limit.
Likelihood: Medium
Depends on the distribution of Snow
tokens. If "whales" (holders of very large amounts of Snow
tokens) exist and are eligible for the airdrop, they are likely to trigger this condition.
Impact: Low
Denial of Service for Large Claims: Legitimate users with entitlements to a large number of Snowman NFTs might be unable to have them minted in a single transaction if the gas cost exceeds the block gas limit. Their transaction would revert, effectively denying them their airdrop.
No Direct Fund Loss: This issue does not directly lead to a loss of funds but rather a failure to receive entitled assets.
The mintSnowman
function's for
loop causes gas costs to scale linearly with the number of NFTs minted. The testGas_MintSnowman_LargeAmount
function in test/Snowman.t.sol
demonstrates an authorized minter (simulating the SnowmanAirdrop
contract) attempting to mint a large batch of 500 NFTs. The gas consumed by this single transaction will be logged.
When this test is run, the console output will show the gasUsed
for minting 500 NFTs in a single call. While this specific amount (500) might not exceed typical block gas limits in a test environment, the gasUsed
value will be substantial. If a user were entitled to a significantly larger number of NFTs (e.g., several thousands), the aggregated gas cost from each iteration of the loop in a single transaction could easily surpass the network's block gas limit, causing the transaction to revert. This demonstrates the potential for a gas-related Denial of Service for users with large NFT entitlements.
To prevent transactions from reverting due to block gas limits when minting for recipients with large entitlements, implement a batching mechanism:
Batching in SnowmanAirdrop.sol
(Recommended):
Modify SnowmanAirdrop.sol
's logic. When a user claims and is entitled to a very large number of NFTs (e.g., totalEntitlement
), SnowmanAirdrop.sol
should not call Snowman.sol::mintSnowman(recipient, totalEntitlement)
in one go.
Instead, SnowmanAirdrop.sol
could either:
Perform multiple calls to Snowman.sol::mintSnowman(recipient, batchSize)
in a loop, where batchSize
is a safe number of NFTs to mint per transaction (e.g., 100-200). This would require SnowmanAirdrop.sol
to manage the iteration and potentially be callable multiple times by the user or an admin to continue a large minting process.
Gas-Efficient NFT Standards (Long-Term Consideration):
For future projects or major upgrades, consider using gas-efficient NFT implementations like ERC721A by Azuki, which are specifically designed to reduce gas costs for minting multiple NFTs in a single transaction. This would require a more significant architectural change to Snowman.sol
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.