Trick or Treat

First Flight #27
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: low
Valid

Integer Division Rounding Vulnerability in `trickOrTreat` Function

Summary

The trickOrTreat function in the SpookySwap contract calculates the required cost for minting an NFT based on a multiplier that can result in half-price (1/2), double price (2/1), or normal price (1/1). However, when the cost multiplier numerator is 1 and the denominator is 2, there is a risk of integer division rounding down to zero, allowing users to potentially mint NFTs for free when treat.cost is small. This issue affects the intended cost calculation and payment requirements for obtaining an NFT, posing a potential financial loss for the contract owner.

Vulnerability Details

When the costMultiplierNumerator is 1 and costMultiplierDenominator is 2 (representing a half-price scenario), and if treat.cost is less than 2 wei, the division (treat.cost * 1) / 2 will round down to zero. This results in requiredCost becoming zero due to Solidity's integer division behavior. This allows a user to call trickOrTreat and potentially mint an NFT for free if they send any amount of ETH >= 0, bypassing the intended payment.
The issue is in this line: https://github.com/Cyfrin/2024-10-trick-or-treat/blob/main/src/TrickOrTreat.sol#L70

uint256 requiredCost = (treat.cost * costMultiplierNumerator) / costMultiplierDenominator;

Impact

This vulnerability enables users to bypass the intended cost for minting NFTs under specific scenarios where treat.cost is low, potentially resulting in financial loss for the contract owner due to the unintended free minting of NFTs.

Tools Used

Manual Review

Recommendations

To prevent requiredCost from being zero, introduce a sanity check after calculating the requiredCost to ensure it is always greater than zero, thus avoiding unintended zero-cost transactions. Update the code as follows:

uint256 requiredCost = (treat.cost * costMultiplierNumerator) / costMultiplierDenominator;
require(requiredCost > 0, "Cost rounded down to zero");
Updates

Appeal created

bube Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Very small cost

In case of treat, if the cost of the treat is very small, the user can get NFT for zero `requiredCost` due to rounding. Also, if the cost is small and odd, the user may get a given NFT at a lower price than intended.

Support

FAQs

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