The contract performs integer division in its cost calculations, which can lead to rounding errors and incorrect pricing. Since Solidity uses integer arithmetic, any fractional components resulting from division are truncated. This can cause users to be overcharged or undercharged when purchasing treats, leading to financial discrepancies and user dissatisfaction.
In the trickOrTreat
function, the cost of a treat is adjusted based on a random multiplier:
When costMultiplierNumerator
and costMultiplierDenominator
result in a fraction (e.g., 1/2 for half price), integer division in Solidity truncates any decimal values. This means that the calculated requiredCost
may be less than or greater than the intended value due to rounding down.
Example Scenario:
If a treat costs 5 wei and the user gets a half-price discount, the calculation becomes (5 * 1) / 2 = 2
wei.
The actual half price should be 2.5 wei, but due to integer division, the user is undercharged by 0.5 wei.
Conversely, if the treat cost is 7 wei, half price would ideally be 3.5 wei, but the calculation yields 3 wei, undercharging the user by 0.5 wei.
Financial Discrepancies: Users may be overcharged or undercharged, leading to loss of funds for either the user or the contract owner.
User Dissatisfaction: Inconsistent pricing can erode trust in the platform, resulting in a negative user experience.
Accounting Issues: Over time, these small discrepancies can accumulate, causing significant financial misalignments in the contract's bookkeeping.
Undercharging Scenario:
Treat cost: 5 wei
Multiplier: Half price (1/2)
Calculation: (5 * 1) / 2 = 2
wei
Intended cost: 2.5 wei
Actual cost charged: 2 wei
Undercharge: 0.5 wei
Overcharging Scenario:
Treat cost: 5 wei
Multiplier: Double price (2/1)
Calculation: (5 * 2) / 1 = 10
wei
Intended cost: 10 wei (correct in this case)
Since the double price scenario doesn't involve fractions, it calculates correctly. The issue mainly arises when the result should be a fractional value.
Use Fixed-Point Arithmetic:
Implement fixed-point math to handle decimal values accurately. You can multiply all cost values by a scaling factor (e.g., 1e18) to preserve precision during calculations.
Explicit Rounding Logic:
Decide on a rounding strategy (e.g., round up to the nearest wei) and implement it in the calculation to ensure predictable and fair pricing.
Validate Cost Calculations:
After computing requiredCost
, include a check to ensure it aligns with expected values, preventing significant deviations.
Inform Users:
Clearly document any rounding behavior so users are aware of how prices are calculated.
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.