Core Contracts

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

Lack of Slippage Protection Enables MEV Exploitation in Token Purchase Function

Description

The buy() function lacks slippage protection, making it vulnerable to MEV (Miner Extractable Value) attacks and sandwich attacks. Since the price is deterministic based on time, malicious actors can predict and manipulate transaction ordering to extract value from users' purchases.

Affected code

function buy(uint256 amount) external whenActive {
require(amount <= state.totalRemaining, "Not enough ZENO remaining");
uint256 price = getPrice();
uint256 cost = price * amount;
require(usdc.transferFrom(msg.sender, businessAddress, cost), "Transfer failed");
// ... rest of the function
}
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)
);
}

Vulnerability details

  1. The buy() function calculates the price at execution time without any bounds checking

  2. MEV bots can sandwich user transactions by:

    • Front-running with transactions that cause price changes

    • Including the user's transaction

    • Back-running to profit from the price movement

  3. Given the deterministic price formula based on time, attackers can precisely calculate profitable attack vectors

  4. Users have no way to specify maximum acceptable price, forcing them to accept any price at execution time

Tools Used

Manual Review

Recommended Mitigation Steps

  1. Add a maxPrice parameter to the buy function:

function buy(uint256 amount, uint256 maxPrice) external whenActive {
require(amount <= state.totalRemaining, "Not enough ZENO remaining");
uint256 price = getPrice();
require(price <= maxPrice, "Price exceeded maximum acceptable");
uint256 cost = price * amount;
// ... rest of the function
}
  1. Consider adding a deadline parameter to prevent transactions from staying pending too long

  2. Implement a price oracle with TWAP (Time Weighted Average Price) for more manipulation resistance

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 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.