Trick or Treat

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

Price Change Vulnerability After Partial Payment in resolveTrick Function

Summary

In the SpookySwap contract, the setTreatCost function allows the owner to change the price of a treat at any time, including after a user has initiated a purchase with a partial payment in a "trick" scenario. Since resolveTrick calculates the remaining required payment based on the current price in treatList, this setup allows the owner to raise or lower the treat price after a partial payment. This behavior can lead to inconsistencies in transaction costs, causing users to pay more than expected or encounter failed transactions.

Vulnerability Details

In a "trick" scenario, the contract requires double the treat’s cost. If the user initially pays less than this required amount, the transaction is stored as a pending purchase. However, since the resolveTrick function references the price from treatList, any price updates by the owner using setTreatCost apply immediately to the pending purchase.

Key Issue:

  • Price Lock Absence: There is no mechanism to lock the treat’s price at the time of the initial purchase. Thus, a pending transaction’s cost is directly impacted by any price changes made afterward.

Impact

  • Increased Costs for Users: Users may face unexpected additional costs if the treat price is raised after their initial payment.

  • Transaction Failures: Users may be unable to complete their purchase if they cannot meet the updated price requirements.

  • Trust and Transparency Issues: Allowing price changes after a partial payment can lead to user distrust and reduce confidence in the platform’s fair pricing.

Tools Used

Manual Review

Recommendations

To ensure consistent and fair pricing, implement the following changes:

Lock Price at Initial Purchase:

  • Store the treat’s cost at the time of the initial purchase and use this locked price in resolveTrick to calculate the remaining required payment. This prevents any impact from future price changes.

mapping(uint256 => uint256) public pendingNFTsOriginalPrice;
  • Set pendingNFTsOriginalPrice[tokenId] in the trickOrTreat function to lock the price at the time of partial payment. The resolveTrick function then uses this locked price, ensuring price changes by the owner do not affect users with pending transactions.

pendingNFTsOriginalPrice[tokenId] = treat.cost;
Updates

Appeal created

bube Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[invalid] Change cost between the call of trickOrTreat and resolveTrick

Only the owner has the rights to change the cost of the treat. Therefore it is assumed that the owner will not change the cost of the pending NFTs. The owner role is trusted.

Support

FAQs

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