3. Market Mechanics3.4 Bid Sniping Prevention

3.4. Bid Sniping Prevention

In traditional ascending or open sealed-bid auctions, Bid Sniping is a prevalent attack vector where participants monitor the auction until the final seconds and submit a marginally higher bid to win the asset without giving others time to react. This behavior exploits two weaknesses:

  1. Visibility: Bidders can see the current highest price.
  2. Timing: The auction allows bids right up until the very last block.

Fhenix-FairMarket v2.0 neutralizes sniping by rendering the target invisible and enforcing a hard cryptographic closure. Since all bids are encrypted (Sealed-Bid), a sniper has no data to target—they cannot see the current highest bid or the number of active participants. Furthermore, the protocol employs an Immutable State Lock at endTime to prevent any post-deadline manipulation.

Core Prevention Mechanisms

MechanismImplementationImpact on Sniping
Cryptographic BlindnessAll bids are stored as bytes32 ciphertext hashes via O(1) storage.Snipers cannot see the current high bid to “top it up” by a minimal increment.
Immutable State ClosureThe triggerFinalize() function atomically transitions state from ACTIVE to RESOLVING.Once the state changes, any pending or late bid transactions revert instantly.
Asynchronous ResolutionBid comparison happens off-chain at DecryptionRequested.Block ordering at the final second becomes irrelevant; all bids submitted before endTime are evaluated equally.
Dynamic Dead Man’s SwitchAuto-voids the auction if triggerFinalize is delayed by network congestion.Prevents malicious actors from exploiting network halts to extend the “bidding window.”

️ Technical Implementation

1. Hard State Closure (placeBid)

The smart contract enforces a strict temporal boundary. Any bid submitted after endTime is rejected, regardless of block inclusion order or gas price.

// packages/contracts/core/FhenixFairMarket.sol
function placeBid(uint256 auctionId, InEuint32 calldata encryptedBid) external {
 // 1. Enforce strict temporal limit
 require(block.timestamp < auctions[auctionId].endTime, "Auction expired");
 
 // 2. Ensure state is still accepting bids
 require(auctions[auctionId].state == AuctionState.ACTIVE, "Auction already resolving");
 
 // 3. Encrypted Solvency Check
 FHE.lte(encryptedBid, FHE.asEuint32(escrowBalances[msg.sender]));
 
 // 4. Commit ciphertext hash (Blind storage)
 bytes32 bidHash = keccak256(abi.encode(encryptedBid));
 auctions[auctionId].ciphertextHashes.push(bidHash);
 
 emit BidPlaced(auctionId, msg.sender, bidHash);
}

2. Atomic Finalization Trigger (triggerFinalize)

The protocol designates triggerFinalize() as a public function incentivized by a 0.2% bounty. Once executed, it locks the registry immediately.

function triggerFinalize(uint256 auctionId) external {
 require(auctions[auctionId].state == AuctionState.ACTIVE, "Invalid state");
 require(block.timestamp >= auctions[auctionId].endTime, "Auction not ended yet");
 
 // Atomic state transition: No new bids can be added after this point
 auctions[auctionId].state = AuctionState.RESOLVING;
 
 // Emit event for off-chain CoFHE processing
 emit DecryptionRequested(auctionId, auctions[auctionId].ciphertextHashes);
 
 // 0.2% Keeper incentive is calculated/released in implementation logic
}

Sniping Defense Flow

️ Security & Economic Guarantees

  1. Value Irrelevance: Since bids are sealed via FHE, a sniper is guessing blindly. They must bid their true maximum value to have a chance of winning, which defeats the purpose of “sniping” for a cheap win.
  2. Gas Competition Neutrality: In standard auctions, snipers use high gas to out-compete other bidders in the mempool. Here, since placeBid stores only a hash and requires no on-chain comparison, the “Gas War” for the last block provides no advantage other than securing a spot in the ciphertext registry.
  3. No “Soft Close” Loopholes: Unlike platforms that extend the timer if a bid is placed in the last minute (to prevent sniping), Fhenix-FairMarket maintains a strict endTime. This ensures predictability for the Keeper automation and the Dynamic Timeout safety net.
  4. Mempool Opacity: Even if a sniper sees a placeBid transaction in the mempool, the payload is an InEuint32 ciphertext. They cannot parse the value to determine if they need to counter-bid.

Comparative Analysis

FeatureTraditional Auction (Open)Fhenix Sealed-Bid
VisibilityFull visibility of high bidOpaque (Ciphertext Hash only)
Sniper StrategyWait & Increment by 1 ETHBlind Guess / Bid Max Value
Late Bid ValueHigh (Wins by timing)Low (Wins by value only)
FinalitySoft Close (often) or Hard CloseHard State Lock (RESOLVING)
Post-Auction DisputesCommon (Did I win? Was I outbid?)Zero (Decrypted result is final)

Audit Gate Compliance (P0)

The protocol enforces strict sniping prevention verification gates. Progression is blocked until all P0 items pass:

  • [] Temporal Guard: placeBid reverts with "Auction expired" if block.timestamp >= endTime.
  • [] State Guard: placeBid reverts with "Auction already resolving" if state is RESOLVING or FINALIZED.
  • [] Atomic Transition: triggerFinalize successfully changes state to RESOLVING in a single transaction, blocking subsequent bids.
  • [] No Late Acceptance: Unit tests confirm that bids submitted in the exact block of finalization (after the state change tx) are rejected.
  • [] Dynamic Timeout Safety: DynamicTimeout.test.ts verifies that if triggerFinalize is not called due to network halt, the auction voids safely rather than staying open for snipers.

Next Steps