Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Valid

Auction duration mismatch

Root + Impact

Description

  • According to the documentation auctions need to be of an exact duration of 3 days from when bidding opens and enough time needs to be left for participants to discover and bid for NFTs

  • The contract implements a 15 minute auction duration instead of the 3 days

// BidBeastsNFTMarketplace.sol
// --- Constants ---
uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes; // @> 15 minutes not 3 days
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ...
if (previousBidAmount == 0) {
requiredAmount = listing.minPrice;
require(msg.value > requiredAmount, "First bid must be > min price");
listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION; // @> Sets 15minute timer
emit AuctionExtended(tokenId, listing.auctionEnd);
} else {
// ...
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION; // @> Extends by 15 minutes
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}
// ...
}

Risk

Likelihood:

  • All users interacting with the protocol will experience this timing mismatch

  • Every auction will use the 15 minute duration instead of the expected 3 day period

Impact:

  • Bidders miss auctions entirely when expecting 3 day duration but finding 15 minute windows

  • NFT sellers receive suboptimal prices due to limited bidding

Proof of Concept

function testAuctionEndsIn15MinutesNot3Days() public {
address seller = address(0x1);
address bidder1 = address(0x2);
address bidder2 = address(0x3);
// Seller lists NFT expecting 3 day auction
vm.prank(owner);
nft.mint(seller, 1);
vm.startPrank(seller);
nft.approve(address(marketplace), 1);
marketplace.listNFT(1, 1 ether, 0); // No buy now pure auction
vm.stopPrank();
// Bidder1 places first bid expecting 3day auction
vm.deal(bidder1, 1.1 ether);
vm.prank(bidder1);
marketplace.placeBid{value: 1.1 ether}(1);
// Get auction end time
(, , , uint256 auctionEnd, ) = marketplace.listings(1);
// Auction ends in 15 minutes not 3 days
assertEq(auctionEnd, block.timestamp + 15 minutes);
// Bidder2 arrives 1 hour later expecting 71 hours remaining
vm.warp(block.timestamp + 1 hours);
vm.deal(bidder2, 2 ether);
vm.prank(bidder2);
vm.expectRevert("Auction ended");
marketplace.placeBid{value: 2 ether}(1);
// NFT sold for 1.1 ETH instead of potential 2 ETH
}

Recommended Mitigation

- uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
+ uint256 constant public S_AUCTION_EXTENSION_DURATION = 3 days;
Updates

Lead Judging Commences

cryptoghost Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts Marketplace: Improper Documentation

Documentation for BidBeasts Marketplace is incomplete or inaccurate, potentially leading to misconfigurations or security misunderstandings.

Support

FAQs

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

Give us feedback!