Bid Beasts

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

Auction Duration Specification Mismatch

Root + Impact

Description

The documentation specifies that auctions should last for 3 days, after which anyone can finalize the auction by calling endAuction(tokenId).
However, the contract implementation initializes auctionEnd to 15 minutes after the first bid and further extends it by 15 minutes when bids are placed near the end of the auction.

This introduces a discrepancy between the expected behavior (fixed 3-day auction) and the implemented behavior (rolling extension auction). Users relying on the documentation may expect their auctions to last 3 days, but in reality, they may end much earlier or later depending on bid activity.

// Root cause in the codebase with @> marks
if (previousBidAmount == 0) {
requiredAmount = listing.minPrice;
require(msg.value > requiredAmount, "First bid must be > min price");
@> listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION; // only 15 minutes
emit AuctionExtended(tokenId, listing.auctionEnd);
} else {
...
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
@> listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION; // rolling extension
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}

Risk

Likelihood:

  • Documentation explicitly states a 3-day auction duration, so users will reasonably rely on this expectation.

  • Every auction created will inherit the mismatched timing logic, so the condition occurs consistently across deployments.

Impact:

  • Auctions may end far earlier than 3 days (only 15 minutes if no further bids are placed).

  • Alternatively, auctions may be extended indefinitely, diverging significantly from the advertised fixed duration.

Proof of Concept

This test shows that the contract does not match the documented auction duration:

  1. _listNFT() creates a new listing.

  2. placeBid sets auctionEnd to 15 minutes after the first bid.

  3. The first assertEq confirms the actual end time (15 minutes).

  4. The second assertEq compares it to the documented 3-day duration, which fails.

It demonstrates a mismatch between the contract behavior and the specification.

function test_durationSpecification() public {
_mintNFT();
_listNFT();
// Place first bid
vm.prank(BIDDER_1);
market.placeBid{value: MIN_PRICE + 1}(TOKEN_ID);
// Observe that auctionEnd = block.timestamp + 15 minutes
assertEq(market.getListing(TOKEN_ID).auctionEnd, block.timestamp + 15 minutes);
// Documentation states auction should end at block.timestamp + 3 days
assertEq(market.getListing(TOKEN_ID).auctionEnd, block.timestamp + 3 days); // fails
}

Recommended Mitigation

To align the contract implementation with the documentation, auctions should have a fixed 3-day duration without rolling extensions.

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

And remove the rolling extension logic that continuously prolongs auctions:

- if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
- listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
- emit AuctionExtended(tokenId, listing.auctionEnd);
- }

This ensures that:

  • Auctions always end exactly 3 days after the first bid.

  • Users and bidders can rely on the documented auction timeline.

Updates

Lead Judging Commences

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