Bid Beasts

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

Mismatch Requirements : Auction Duration And Settlement Mechanism

Root + Impact

The auction mechanism implementation doesn't match the 3-day fixed duration required in the project specifications, using a dynamic 15-minute initial duration with extensions instead.

Description

  • According to the requirements, auctions should have a fixed 3-day duration after which anyone can call endAuction() (method names are also different specified in requirement doc) to finalize the auction.

*The actual implementation sets auction end time to only 15 minutes after first bid and includes an anti-sniping extension mechanism that extends the auction by 15 minutes when bids are placed near the end, with no 3-day fixed duration anywhere in the contract.

// Constants define auction extension duration of 15 minutes instead of 3 days
@> uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
// In placeBid function, when first bid is placed:
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);
}
// Auction extension mechanism not mentioned in requirements:
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
@> listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
}
// Settlement function name differs from requirements
@> function settleAuction(uint256 tokenId) external isListed(tokenId) {
// ...
}

Risk

Likelihood: High

  • Every auction listed in the marketplace has this incorrect timing behavior because it is hardcoded into the contract

  • All auction settlements are affected as no auction follows the required 3-day fixed period

Impact: High

  • Users expecting a fixed 3-day auction will encounter a completely different mechanism with much shorter initial duration

  • The unexpected auction extensions could lead to confusion and disputes between buyers and sellers who had different expectations about when auctions would end

  • Without the fixed 3-day period, the marketplace behavior fundamentally differs from what was documented and expected

Proof of Concept

The issue can be verified by examining the auction lifecycle:

// 1. When NFT is listed, no auction end time is set
function listNFT(uint256 tokenId, uint256 _minPrice, uint256 _buyNowPrice) external {
// ...
listings[tokenId] = Listing({
seller: msg.sender,
minPrice: _minPrice,
buyNowPrice: _buyNowPrice,
auctionEnd: 0, // Timer starts only after the first valid bid
listed: true
});
// ...
}
// 2. First bid sets auction to end in just 15 minutes
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ...
if (previousBidAmount == 0) {
// ...
listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
}
// ...
}
// 3. Subsequent bids can extend the auction by additional 15-minute increments
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
}

Recommended Mitigation

Modify the contract to align with the required 3-day auction period:

- uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
+ uint256 constant public S_AUCTION_DURATION = 3 days;
+ uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes; // Keep if anti-sniping is desired
// In the listNFT function:
listings[tokenId] = Listing({
seller: msg.sender,
minPrice: _minPrice,
buyNowPrice: _buyNowPrice,
- auctionEnd: 0, // Timer starts only after the first valid bid
+ auctionEnd: block.timestamp + S_AUCTION_DURATION, // Fixed 3-day period from listing
listed: true
});
// In placeBid function:
- 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);
- }
+ if (previousBidAmount == 0) {
+ requiredAmount = listing.minPrice;
+ require(msg.value > requiredAmount, "First bid must be > min price");
+ // Auction end already set at listing time
+ }
Updates

Lead Judging Commences

cryptoghost Lead Judge
2 months ago
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!