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.
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
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.
Manual Review
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:
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.
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.