Bid Beasts

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

Bid-Based Time Extensions Create Never-Ending Auctions

Time extension causing a never ending of the auction

Description

  • The auction time extension logic incorrectly adds fixed duration to the current auction end time instead of setting a minimum end time from the current block timestamp. This creates a scenario where auctions can be extended indefinitely, preventing them from ever ending and making the `settleAuction` function unusable in placeBid() function.

  • Each bid extends the auction by fixed duration from the current end time, not from current time. This creates compounding extensions that push the end time infinitely into the future.

require(msg.sender != previousBidder, "Already highest bidder"); // @Not_a_bug Isn't the requirement coming at the wrong time ??
emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value); // @solve Wrong amount specified
// --- Regular Bidding Logic ---
//Code here ...
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;
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}

Likelihood:

  • Every bid placed within the final 15 minutes of an auction extends the duration by a full 15 minutes from the current end time

Impact:

  • settleAunction function is unusable

  • infinite bidding wars causing wasted gas on unwinnable auctionsImpact 2

PoC

Add this to the test file and run it:

function test_ExcessiveAuctionDuration() public {
_mintNFT();
_listNFT();
uint256 extensionDuration = market.S_AUCTION_EXTENSION_DURATION();
console.log("=== EXCESSIVE AUCTION DURATION BUG ===");
console.log(
"Auction extension duration:",
extensionDuration,
"seconds (15 minutes)"
);
// First bid - starts the auction
vm.prank(BIDDER_1);
market.placeBid{value: 2 ether}(TOKEN_ID);
BidBeastsNFTMarket.Listing memory listing = market.getListing(TOKEN_ID);
uint256 firstAuctionEnd = listing.auctionEnd;
console.log("First bid - Auction ends at:", firstAuctionEnd);
console.log(
"Time until end:",
firstAuctionEnd - block.timestamp,
"seconds"
);
// Second bid: 1 minute before end → SHOULD extend
vm.warp(firstAuctionEnd - 60); // 60 seconds before end
vm.prank(BIDDER_2);
market.placeBid{value: 3 ether}(TOKEN_ID);
listing = market.getListing(TOKEN_ID);
uint256 secondAuctionEnd = listing.auctionEnd;
console.log(
"Second bid (1min before end) - New end:",
secondAuctionEnd
);
console.log(
"Time added:",
secondAuctionEnd - firstAuctionEnd,
"seconds"
);
console.log(
"Total auction duration so far:",
secondAuctionEnd - block.timestamp,
"seconds"
);
// BUG DEMONSTRATION: Third bid with 10 MINUTES remaining still extends!
vm.warp(secondAuctionEnd - 600); // 600 seconds = 10 MINUTES before end
uint256 timeBeforeBid = block.timestamp;
vm.prank(BIDDER_1);
market.placeBid{value: 4 ether}(TOKEN_ID);
listing = market.getListing(TOKEN_ID);
uint256 thirdAuctionEnd = listing.auctionEnd;
// Verify auction is still ongoing (as expected with bad time logic)
vm.expectRevert("Auction has not ended");
market.settleAuction(TOKEN_ID);
console.log(
"settleAuction reverts - auction still active as long as there will be a new bidder... no limit"
);
}

Recommended Mitigation


Implement a maximum auction deadline that prevents any auction from extending beyond 24 hours from its start time, ensuring all auctions eventually end.
// Add maximum auction duration constant
+ uint256 public constant S_MAX_AUCTION_DURATION = 24 hours; //Or more
// In placeBid function, modify the time extension logic:
} else {
// code here ....
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
// Calculate new end time with maximum duration limit
+ uint256 newEndTime = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
+ uint256 maxAllowedEnd = listing.startTime + S_MAX_AUCTION_DURATION;
// Enforce maximum auction duration
+ if (newEndTime > maxAllowedEnd) {
listing.auctionEnd = maxAllowedEnd;
+ } else {
listing.auctionEnd = newEndTime;
+ }
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}
Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeast Marketplace: Auction Duration Miscalculation

BidBeast marketplace contains a flaw in its auction timing mechanism. This causes the contract to miscalculate the actual end time of an auction, resulting in auctions that either conclude prematurely or run longer than specified.

Support

FAQs

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