Core Contracts

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

Incorrect Price Formula in Auction::getPrice Leading to Rounding Errors

Summary

The getPrice function in the Auction contract uses integer division to calculate the price decay over time. This approach can lead to rounding errors, causing the calculated price to deviate from the intended formula. As a result, earlier or later buyers may be favored due to improper rounding, potentially underpaying or overpaying the protocol.

Vulnerability Details

Integer Division in Price Calculation :

  • The getPrice function calculates the current price as:

    return state.startingPrice - (
    (state.startingPrice - state.reservePrice) *
    (block.timestamp - state.startTime) /
    (state.endTime - state.startTime)
    );
  • Solidity performs integer division, which truncates fractional results. If (block.timestamp - state.startTime) is not perfectly divisible by (state.endTime - state.startTime), the result will be rounded down, leading to inaccuracies in the price calculation.

  • The intended formula for price is:

price(t) = startingPrice - (ΔPrice * elapsed / duration)
  • Due to integer division, the actual price may differ slightly from this formula, especially when elapsed % duration != 0.

Examples

  • Suppose:

    • startingPrice = 1000

    • reservePrice = 500

    • startTime = 100

    • endTime = 200

    • block.timestamp = 150

    The intended price at t = 150 is:

price(150) = 1000 - ((1000 - 500) * (150 - 100) / (200 - 100))
= 1000 - (500 * 50 / 100)
= 1000 - 250
= 750

However, if elapsed = 51 instead of 50 (due to block timing variations), the calculation becomes:

price(151) = 1000 - ((1000 - 500) * 51 / 100)
= 1000 - (500 * 51 / 100)
= 1000 - 255
= 745

Here, the price is slightly lower than intended due to truncation during integer division.

Impact

  • Depending on the direction of the rounding error, earlier or later buyers may pay slightly less or more than intended, this creates an unfair advantage or disadvantage for certain buyers.

Tools Used

Manual Review

Recommendations

  • Use higher precision (e.g., multiply before dividing):

uint256 priceDiff = state.startingPrice - state.reservePrice;
uint256 elapsed = block.timestamp - state.startTime;
uint256 price = state.startingPrice - (priceDiff * elapsed) / (state.endTime - state.startTime);

This fixed the issue

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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