Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: low
Invalid

Auction Price Calculation Underflow Due to Improper Parameter Ordering

Summary

The Auction contract’s getPrice() function subtracts the reserve price from the starting price. If the starting price is set lower than the reserve price, this subtraction underflows, causing the function to revert. This error prevents the auction from operating correctly and can block bidding.

Vulnerability Details

The getPrice() function calculates the current auction price with the following logic:

function getPrice() public view returns (uint256) {
if (block.timestamp < state.startTime) return state.startingPrice;
if (block.timestamp >= state.endTime) return state.reservePrice;
return state.startingPrice - (
(state.startingPrice - state.reservePrice) *
(block.timestamp - state.startTime) /
(state.endTime - state.startTime)
);
}
  • Issue:
    The calculation state.startingPrice - state.reservePrice must be non-negative. If state.startingPrice is less than state.reservePrice, the subtraction underflows (since these are unsigned integers), causing the function to revert. This vulnerability arises from not validating the auction parameters upon initialization.

Proof-of-Concept (POC)

Example:

  • Auction Parameters:

    • state.startingPrice = 50 USDC

    • state.reservePrice = 100 USDC

    • Auction duration: 100 seconds

  • At 50 seconds into the auction:

    • Expected operation:

      Price = 50 - ((50 - 100) x 50/100)

    • Calculation of decrement:

      50 - 100 = Underflow (since unsigned integers cannot be negative)

      • Instead of yielding -50, the operation reverts.

  • Outcome:
    The auction’s price calculation fails, preventing any further bidding or auction progress.

Impact

  • The underflow error will cause the auction to revert, making it impossible for users to bid.

Tools Used

Manual Review

Recommendations

Add a validation check in the constructor to ensure that the starting price is greater than or equal to the reserve price. For example:

constructor(
address _zenoAddress,
address _usdcAddress,
address _businessAddress,
uint256 _startTime,
uint256 _endTime,
uint256 _startingPrice,
uint256 _reservePrice,
uint256 _totalAllocated,
address _initialOwner
) Ownable(_initialOwner) {
+ require(_startingPrice >= _reservePrice, "Starting price must be >= reserve price");
zeno = ZENO(_zenoAddress);
usdc = IUSDC(_usdcAddress);
businessAddress = _businessAddress;
state = AuctionState({
startTime: _startTime,
endTime: _endTime,
startingPrice: _startingPrice,
reservePrice: _reservePrice,
totalAllocated: _totalAllocated,
totalRemaining: _totalAllocated,
lastBidTime: 0,
lastBidder: address(0)
});
}

This change ensures that the arithmetic in getPrice() remains valid, preventing underflow and guaranteeing that the auction price decreases correctly to the reserve price.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!