Severity: High
Vulnerability Type: Denial of Service (DoS), Storage Bloat
The SpookySwap contract’s trickOrTreat
function allows users to purchase NFTs at three different price points: standard price, double price ("trick"), and half price ("treat"). However, the double-price ("trick") mechanism introduces a critical vulnerability that can lead to denial of service (DoS) and excessive storage consumption, posing significant risks to the contract’s functionality and performance.
pendingNFTs
MappingThe contract stores NFTs that have been partially paid for but not yet fully purchased in a pendingNFTs
mapping. There is no limit on the number of entries that can be stored in this mapping. This allows a malicious user to repeatedly trigger the "trick" scenario (by only sending the initial portion of the required ETH), resulting in an indefinite number of entries in the pendingNFTs
mapping. This behavior can quickly consume the contract's storage capacity, potentially leading to higher gas costs for any subsequent operations involving the contract.
The contract does not implement a mechanism to prevent duplicate entries for the same user and treat combination within the pendingNFTs
mapping. This can result in multiple entries being created for the same user, leading to inconsistencies, unintended behavior, and further strain on the contract’s storage.
Once an NFT is stored in the pendingNFTs
mapping as a pending transaction, there is no expiration or timeout mechanism. This means that if a user fails to complete the transaction (by calling the resolveTrick
function), the entry remains indefinitely in the contract’s storage. This could result in persistent storage bloat over time, increasing the risk of DoS due to storage exhaustion.
The following code snippet from the trickOrTreat
function illustrates the issue:
Unbounded Mapping: No constraints on the number of pendingNFTs
entries.
Missing Duplicate Checks: No validation to ensure that a user does not have multiple pending entries for the same treat.
No Expiration Mechanism: Entries in pendingNFTs
remain until the user completes the purchase manually.
The following test script demonstrates how an attacker could exploit the vulnerability to perform a denial-of-service attack
Denial of Service (DoS)
An attacker can exploit the absence of restrictions on the pendingNFTs
mapping to create numerous pending entries, effectively filling up the contract's storage space. This can slow down or prevent legitimate users from interacting with the contract, making the trickOrTreat
function and potentially the entire contract unusable.
Storage Bloat
Due to the lack of a limit on pending entries and the absence of an expiration mechanism, the pendingNFTs
mapping can grow uncontrollably. This can significantly increase the gas costs for any transactions interacting with the contract, potentially leading to prohibitive costs for users and making the contract economically unfeasible to use.
The protocol can work correctly with more than 20000 tokens in it. It is informational.
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.