Bid Beasts

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

Incorrect bid increment calculation (precision/overflow)

Root + Impact

Description

  • The next required bid is calculated as: requiredAmount = (previousBidAmount / 100) * (100 + S_MIN_BID_INCREMENT_PERCENTAGE);

  • This does integer division first (loss of precision) and the alternative multiplication-first approach could overflow on extreme values. The current expression may allow slightly smaller-than-intended bids due to truncation.

// Root cause in the codebase with @> marks to highlight the relevant section
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
/**/
// --- Regular Bidding Logic ---
uint256 requiredAmount;
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);
} else {
// This logic here - it should be
= (previousBidAmount*(100 + S_MIN_BID_INCREMENT_PERCENTAGE)) / 100;
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) {
timeLeft = listing.auctionEnd - block.timestamp;
}
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:

  • Medium — But precision/truncation makes the policy ambiguous.

Impact:

  • Medium — can allow a next bid that’s smaller than intended percentage increase, or (with alternative implementations) risk overflow.

Proof of Concept

Recommended Mitigation

- requiredAmount = (previousBidAmount / 100) * (100 + S_MIN_BID_INCREMENT_PERCENTAGE);
+ requiredAmount = (previousBidAmount*(100 + S_MIN_BID_INCREMENT_PERCENTAGE)) / 100;
Updates

Lead Judging Commences

cryptoghost Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts Marketplace: Integer Division Precision Loss

Integer division in requiredAmount truncates fractions, allowing bids slightly lower than intended.

Support

FAQs

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

Give us feedback!