Bid Beasts

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

Incorrect Auction Timer: 15-Min Extension based on Docs/Readme vs. 3-Day Initial Duration Implemented in contract

Incorrect Auction Timer: 15-Min Extension based on Docs/Readme vs. 3-Day Initial Duration Implemented in contract

Description

Documentation specifies 3-day auctions starting on first bid. Code initializes auctionEnd to 15 minutes on first bid, causing early endings instead of full exposure.

if (previousBidAmount == 0) {
requiredAmount = listing.minPrice;
require(msg.value > requiredAmount, "First bid must be > min price");
@>listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION;@>
emit AuctionExtended(tokenId, listing.auctionEnd);
}

Risk

Likelihood:

  • On every first bid in new listings.

  • In auctions needing extended bidder interest.

Impact:

  • Premature closures limit bids, undervaluing NFTs.

  • Misaligns with docs, confusing users and reducing adoption.

Proof of Concept

Lists NFT, places first bid to start 15-min timer, warps time past 15 min, checks auction ended and settle works to show early close vs. 3 days.

function testPrematureAuctionEnd() public {
_mintNFT();
_listNFT();
// First bid starts 15-min timer
vm.deal(BIDDER_1, MIN_PRICE + 0.01 ether);
vm.prank(BIDDER_1);
market.placeBid{value: MIN_PRICE + 0.01 ether}(TOKEN_ID);
// Warp past 15 min
vm.warp(block.timestamp + 16 minutes);
// Auction ended prematurely (should be 3 days)
BidBeastsNFTMarket.Listing memory listing = market.getListing(TOKEN_ID);
assertTrue(block.timestamp >= listing.auctionEnd);
// Can settle
market.settleAuction(TOKEN_ID);
}

Recommended Mitigation

Adds 3-day constant for first bid timer; sets initial end to 3 days; resets extensions to full 15 min from now, not add to remaining.

+uint256 public constant S_AUCTION_DURATION = 3 days;
+uint256 public constant S_AUCTION_EXTENSION_DURATION = 15 minutes;
if (previousBidAmount == 0) {
requiredAmount = listing.minPrice;
require(msg.value >= requiredAmount, "First bid must meet min price");
- listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION;
+ listing.auctionEnd = block.timestamp + S_AUCTION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
} else {
requiredAmount = (previousBidAmount / 100) * (100 + S_MIN_BID_INCREMENT_PERCENTAGE);
require(msg.value >= requiredAmount, "Bid not high enough");
uint256 timeLeft = 0;
if (listing.auctionEnd > block.timestamp) {
timeLeft = listing.auctionEnd - block.timestamp;
}
- if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
- listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
+ if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
+ listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}
Updates

Lead Judging Commences

cryptoghost Lead Judge
about 1 month ago
cryptoghost Lead Judge about 1 month 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.