Trick or Treat

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

Treat cost can be set to Zero by addTreat

Summary

The addTreat function in SpookySwap contract allows the creation of treats with zero cost. This vulnerability enables the minting of NFTs without any Ether payment, just the gas transaction.

Vulnerability Details

In the current implementation, the addTreat function does not validate the _rate parameter, allowing treats to be added with a cost of zero. This could allow a malicious owner or a mistakenly configured setup to create NFTs that users can mint without paying any ETH, disrupting the protocol's ecosystem like for example the trickOrTreat function.

function addTreat(string memory _name, uint256 _rate, string memory _metadataURI) public onlyOwner {
treatList[_name] = Treat(_name, _rate, _metadataURI);
treatNames.push(_name);
emit TreatAdded(_name, _rate, _metadataURI);
}

With this current implementation, the following test should fail to revert.

function testAddTreatWithZeroCost() public {
vm.prank(owner);
vm.expectRevert("Treat cost must be more than zero.");
spookySwap.addTreat("GhostPepper", 0, "ipfs://Qm...GhostPepper");
}

Impact

This vulnerability can indirectly affect the value and integrity of the NFTs in the protocol. Treats with zero-cost allow users to mint without paying the required ETH, potentially devaluing existing NFTs and disrupting the intended supply and demand mechanism.

  • Severity: Medium

  • Impact on Funds: Indirect (no immediate loss of funds but affects protocol stability and value)

  • Likelihood of Exploitation: High (can be exploited by owner at any time)

Tools Used

Manual review and unit tests using Foundry.

Recommendations

Implement a validation check in the addTreat function to ensure that the _rate parameter is greater than zero before adding a treat. This will prevent the creation of zero-cost NFTs and align with the protocol’s intended cost-based access model.

function addTreat(string memory _name, uint256 _rate, string memory _metadataURI) public onlyOwner {
require(_rate > 0, "Treat cost must be greater than zero.");
treatList[_name] = Treat(_name, _rate, _metadataURI);
treatNames.push(_name);
emit TreatAdded(_name, _rate, _metadataURI);
}

With this added line, the test we ran previously in our PoC passes as it should.

Updates

Appeal created

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

[invalid] Zero treat cost

The cost of the treat is set only by the owner (in the constructor, in addTreat and in setTreatCost). That means the cost of the treat will always be greater than zero.

Support

FAQs

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