Beginner FriendlyFoundryGameFi
100 EXP
View results
Submission Details
Severity: high
Invalid

MartenitsaMarketplace::listMartenitsaForSale does not have a cap on the price of the martenitsa that can be listed for sale.

Summary

MartenitsaMarketplace::listMartenitsaForSale does not have a cap on the price of the martenitsa that can be listed for sale, This can be exploited to list martenitsa for sale at an exorbitant price for the users.

Vulnerability Details

When a Producer lists a martenitsa for sale, they can set the price of the martenitsa. There is no check to ensure that the price of the martenitsa is reasonable. This can be exploited by a malicious Producer to list a martenitsa for sale at an exorbitant price.

function listMartenitsaForSale(uint256 tokenId, uint256 price) external {
require(msg.sender == martenitsaToken.ownerOf(tokenId), "You do not own this token");
require(martenitsaToken.isProducer(msg.sender), "You are not a producer!");
@> require(price > 0, "Price must be greater than 0");
Listing memory newListing = Listing({
tokenId: tokenId,
seller: msg.sender,
price: price,
design: martenitsaToken.getDesign(tokenId),
forSale: true
});
tokenIdToListing[tokenId] = newListing;
emit MartenitsaListed(tokenId, msg.sender, price);
}
POC

Add this test to MartenitsaMarketplace.test.sol:

function testListMartenitsaForSalePOC_HighPrice() public createMartenitsa {
vm.prank(chasy);
marketplace.listMartenitsaForSale(0, 1_200 ether);
list = marketplace.getListing(0);
assert(list.seller == chasy);
assert(list.price == 1_200 ether);
}

Test output:

Ran 1 test for test/MartenitsaMarketplace.t.sol:MartenitsaMarketplace
[PASS] testListMartenitsaForSalePOC_HighPrice() (gas: 332503)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.92ms (394.25µs CPU time)

When the Producer chasy lists a martenitsa for sale at a price of 1_200 ether, the transaction is successful. This can be exploited by a malicious Producer to list a martenitsa for sale at an exorbitant price.

Impact

A malicious Producer can list a martenitsa for sale at an exorbitant price, which can be detrimental to the users.

Tools Used

Foundry and Manual review.

Recommendations

Add a cap on the price (Maximum price of a martenitsa token) of the martenitsa that can be listed for sale.

We add a state variable maxPrice to the contract and set it to a reasonable value. We then add a check in the listMartenitsaForSale function to ensure that the price of the martenitsa being listed for sale is less than or equal to maxPrice. Example: 1 ETH as the maximum price.

+ uint256 public maxPrice = 1e18; // 1 ETH
function listMartenitsaForSale(uint256 tokenId, uint256 price) external {
require(msg.sender == martenitsaToken.ownerOf(tokenId), "You do not own this token");
require(martenitsaToken.isProducer(msg.sender), "You are not a producer!");
require(price > 0, "Price must be greater than 0");
+ require(price <= maxPrice, "Price is too high");
Listing memory newListing = Listing({
tokenId: tokenId,
seller: msg.sender,
price: price,
design: martenitsaToken.getDesign(tokenId),
forSale: true
});
tokenIdToListing[tokenId] = newListing;
emit MartenitsaListed(tokenId, msg.sender, price);
}
Updates

Lead Judging Commences

bube Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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