Bid Beasts

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

Auction Duration Mismatch Creates Extremely Short Auctions

Auction Duration Mismatch Creates Extremely Short Auctions

Description

  • The protocol documentation specifies that auctions should have an "Auction deadline of exactly 3 days" to provide sufficient time for competitive bidding.

  • The contract implementation sets the auction duration to only 15 minutes (S_AUCTION_EXTENSION_DURATION) instead of the documented 3 days, creating extremely short auction windows that prevent proper price discovery.

In src/BidBeastsNFTMarketPlace.sol:

contract BidBeastsNFTMarket is Ownable(msg.sender) {
// ... existing code ...
@> uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
//existing code
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ... existing code ...
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 15 minutes instead of 3 days
emit AuctionExtended(tokenId, listing.auctionEnd);
}
// ... rest of function ...
}

Risk

Likelihood:

  • This occurs on every first bid placed on any NFT listing, as the auction timer is automatically set to the incorrect duration.

  • The 15-minute window is far too short for most users to discover and participate in auctions, especially across different time zones.

  • Users expect 3-day auctions based on the protocol specification and will miss bidding opportunities.

Impact:

  • Sellers receive significantly lower sale prices due to insufficient time for competitive bidding and price discovery.

  • Most potential bidders miss auction opportunities due to the extremely short 15-minute window.

Proof of Concept

First we need to make a quick fix in test/BidBeastsMarketPlaceTest.t.sol:BidBeastsNFTMarketTest::setUp()

function setUp() public {
// Deploy contracts
- vm.prank(OWNER);
+ vm.startPrank(OWNER);
nft = new BidBeasts();
market = new BidBeastsNFTMarket(address(nft));
rejector = new RejectEther();
vm.stopPrank();
// Fund users
vm.deal(SELLER, STARTING_BALANCE);
vm.deal(BIDDER_1, STARTING_BALANCE);
vm.deal(BIDDER_2, STARTING_BALANCE);
}

Please add the following test to test/BidBeastsMarketPlaceTest.t.sol:BidBeastsNFTMarketTest:

function testSecondBidderCanNotBidAfter1Day() public {
_mintNFT();
_listNFT();
/* ------------------------------ BIDDER_1 bids ----------------------------- */
vm.prank(BIDDER_1);
market.placeBid{value: MIN_PRICE + 1}(TOKEN_ID);
BidBeastsNFTMarket.Bid memory highestBid = market.getHighestBid(TOKEN_ID);
assertEq(highestBid.bidder, BIDDER_1);
assertEq(highestBid.amount, MIN_PRICE + 1);
assertEq(market.getListing(TOKEN_ID).auctionEnd, block.timestamp + market.S_AUCTION_EXTENSION_DURATION());
/* ------------------------ BIDDER_2 bids after 1 day ----------------------- */
vm.warp(block.timestamp + 1 days);
vm.roll(block.number + 10);
vm.prank(BIDDER_2);
vm.expectRevert("Auction ended");
market.placeBid{value: MIN_PRICE + 1}(TOKEN_ID);
}

Then run forge test --mt testSecondBidderCanNotBidAfter1Day

Output:

Ran 1 test for test/BidBeastsMarketPlaceTest.t.sol:BidBeastsNFTMarketTest
[PASS] testSecondBidderCanNotBidAfter1Day() (gas: 305572)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 4.54ms (456.07µs CPU time)

Recommended Mitigation

Update the auction duration constant to match the 3-day specification:

+ uint256 constant public S_AUCTION_DURATION = 3 days;
uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ... existing code ...
if (previousBidAmount == 0) {
requiredAmount = listing.minPrice;
require(msg.value > requiredAmount, "First bid must be > min price");
- listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION;
+ listing.auctionEnd = block.timestamp + S_AUCTION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
} else {
// Keep extension logic for subsequent bids
// ... existing extension logic using S_AUCTION_EXTENSION_DURATION ...
}
}
Updates

Lead Judging Commences

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.