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:
- Visibility: Bidders can see the current highest price.
- 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
| Mechanism | Implementation | Impact on Sniping |
|---|---|---|
| Cryptographic Blindness | All 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 Closure | The triggerFinalize() function atomically transitions state from ACTIVE to RESOLVING. | Once the state changes, any pending or late bid transactions revert instantly. |
| Asynchronous Resolution | Bid 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 Switch | Auto-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
- 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.
- Gas Competition Neutrality: In standard auctions, snipers use high gas to out-compete other bidders in the mempool. Here, since
placeBidstores 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. - 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 theKeeperautomation and theDynamic Timeoutsafety net. - Mempool Opacity: Even if a sniper sees a
placeBidtransaction in the mempool, the payload is anInEuint32ciphertext. They cannot parse the value to determine if they need to counter-bid.
Comparative Analysis
| Feature | Traditional Auction (Open) | Fhenix Sealed-Bid |
|---|---|---|
| Visibility | Full visibility of high bid | Opaque (Ciphertext Hash only) |
| Sniper Strategy | Wait & Increment by 1 ETH | Blind Guess / Bid Max Value |
| Late Bid Value | High (Wins by timing) | Low (Wins by value only) |
| Finality | Soft Close (often) or Hard Close | Hard State Lock (RESOLVING) |
| Post-Auction Disputes | Common (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:
placeBidreverts with"Auction expired"ifblock.timestamp >= endTime. - [] State Guard:
placeBidreverts with"Auction already resolving"if state isRESOLVINGorFINALIZED. - [] Atomic Transition:
triggerFinalizesuccessfully changes state toRESOLVINGin 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.tsverifies that iftriggerFinalizeis not called due to network halt, the auction voids safely rather than staying open for snipers.
Next Steps
- Proceed to 3.5. Sybil Bidding Mitigation to understand how collateral-backed entry barriers prevent ghost bidding.
- Review 4. Execution Roadmap to track the development progress of these features.
- Explore Security Model for comprehensive threat matrices covering MEV and timing attacks.