Core Contracts

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

Inconsistent Auction Ending Mechanism Preventing Bids at `reservePrice` in ZENO Auction Contract

Summary

The Auction.sol contract implements a Gradual Dutch Auction (GDA) system, where the price of ZENO tokens decreases over time until reaching a reserve price. However, due to the whenActive modifier, users cannot bid at t = endTime, preventing them from purchasing tokens at the lowest allowed price (reservePrice). This behavior contradicts the documentation, which states that bidding should continue until the auction reaches its predetermined end time or the full allocation is sold.

Vulnerability Details

Auction pricing logic (getPrice) correctly decreases the price until it reaches reservePrice at t = endTime.

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)
);
}

The buy function has a whenActive modifier.

function buy(uint256 amount) external whenActive {
// buy logic
}

The whenActive modifier prevents bidding at t = endTime, meaning no one can buy at reservePrice.

modifier whenActive() {
require(block.timestamp > state.startTime, "Auction not started");
require(block.timestamp < state.endTime, "Auction ended");
_;
}

According to the project documentation under Auction Mechanism section:

https://docs.raac.io/core/zeno/ZENO_BOND

"The auction price starts at an initial value and decreases at a steady rate until it reaches a floor limit. The price will not drop below this reserve price."

This statement implies that users should be able to bid at the reserve price, ensuring they can purchase tokens at the lowest allowable value before the auction ends.

However, due to the whenActive modifier, bidding is blocked at t = endTime, meaning users are unable to bid at the reserve price, which contradicts the intended auction mechanism.

The getPrice() function correctly returns reservePrice at t = endTime, but the whenActive modifier prevents bids at this time. Hence, users would always pay more than the expected reserve price.

Impact

The auction mechanism does not work as intended as no one can purchase at the lowest price (reservePrice).

Impact Metric Details
Severity Medium
Likelihood High (Users will expect to bid at reserve price)
Funds at Risk Potentially some ZENO tokens remain unsold
User Impact Users miss the chance to buy at reserve price

Tools Used

Manual Review

Recommendations

Update the getPrice function in such a way that reservePrice occurs before reaching the endTime

Or,

Modify the whenActive modifier to allow bidding at t = endTime:

modifier whenActive() {
require(block.timestamp > state.startTime, "Auction not started");
require(block.timestamp <= state.endTime, "Auction ended"); // @audit: Allow bidding at `t = endTime`
_;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Auction.sol's whenActive modifier prevents bidding at endTime when price reaches reservePrice, contradicting documentation and preventing purchases at the intended floor price

Support

FAQs

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