Bid Beasts

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

Auction Duration Mismatch – README vs. Implementation

The auction duration in the contract is set to 15 minutes after the first bid, whereas the README specifies that auctions should last 3 days. This discrepancy between the implemented logic and the documentation causes the auction to end much earlier than expected.

Description

  • The README specifies that all NFT auctions should last exactly 3 days from the first bid. Users expect enough time to place competing bids during this period.

  • In the current implementation, the auction ends 15 minutes after the first bid (S_AUCTION_EXTENSION_DURATION). The timer is extended only by 15 minutes if a subsequent bid is placed close to the end. This is much shorter than the 3-day duration documented in the README.


Vulnerable piece of code

  • If we look at the README.md and the implementation there's a discrepancy. The S_AUCTION_EXTENSION_DURATION variable is set to 15 minutes and is added to the current block.timestamp i.e only 15 minutes and is stored in the auctionEnd property of the Listing struct

  • The README.md that the auction end after 3 days but to this issue it ends in just 15 minutes after 1st bidding.

// This is the variable delaration for auction extension
@> uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
// This is the function Responsible for bidding
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
Listing storage listing = listings[tokenId];
address previousBidder = bids[tokenId].bidder;
uint256 previousBidAmount = bids[tokenId].amount;
require(listing.seller != msg.sender, "Seller cannot bid");
// auctionEnd == 0 => no bids yet => allowed
// auctionEnd > 0 and block.timestamp >= auctionEnd => auction ended => block
require(listing.auctionEnd == 0 || block.timestamp < listing.auctionEnd, "Auction ended");
// ----------------------------------------- Regular Bidding Logic ------------------------------------
uint256 requiredAmount;
if (previousBidAmount == 0) { ////////for 1st bid
requiredAmount = listing.minPrice;
require(msg.value > requiredAmount, "First bid must be > min price");
listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION; // bid + 15 minutes
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) { // 15600010 - 15600000 = 10
timeLeft = listing.auctionEnd - block.timestamp;
// 10 = 15600010 - 15600000
}
// 0 < 15 minutes
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
@> listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}
// EFFECT: update highest bid
bids[tokenId] = Bid(msg.sender, msg.value);
if (previousBidder != address(0)) {
_payout(previousBidder, previousBidAmount);
}
emit BidPlaced(tokenId, msg.sender, msg.value);
}

Risk

Likelihood:

  • High, because this occurs for every NFT listed and bid.

  • Any auction with at least one bid will only last 15 minutes unless extended, contrary to user expectations.

Impact:

  • Users may miss opportunities to participate in auctions.


Sellers may receive fewer bids than anticipated, reducing potential revenue.

  • Misleading documentation can lead to loss of trust in the platform.

Proof of Concept

  • In this test we can clearly see that just after 16 minutes of first we aren't able to make the 2nd bid because auction has ended.

function test_AuctionEndcheck() public {
_mintNFT();
_listNFT();
vm.prank(BIDDER_1);
market.placeBid{value: 2 ether}(TOKEN_ID);
vm.warp(block.timestamp + 16 minutes);
vm.prank(BIDDER_2);
market.placeBid{value: 3 ether}(TOKEN_ID);
}
/*
Ran 1 test for test/anyoncecanwithdraw.t.sol:BidBeastsNFTMarketTest
[FAIL: Auction ended] test_AuctionEndcheck() (gas: 335258)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 1.12ms (206.80µs CPU time)
Ran 1 test suite in 17.05ms (1.12ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/anyoncecanwithdraw.t.sol:BidBeastsNFTMarketTest
[FAIL: Auction ended] test_AuctionEndcheck() (gas: 335258)
*/

Recommended Mitigation

  • There is one simple mitigation just change the value of S_AUCTION_EXTENSION_DURATION from 15 minutes to 3 days.

- uint256 constant public S_AUCTION_EXTENSION_DURATION = 15 minutes;
+ uint256 constant public S_AUCTION_EXTENSION_DURATION = 3 days;
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!