Skip to main content

Threat model

This page enumerates the threats SealedIP defends against and the threats it does not. Read it before assuming the protocol is bulletproof.

What SealedIP defends against

Mempool sniping

Threat: A node operator reads pending bid transactions from the mempool and submits a higher bid in the same block.

Defense: Bid amounts are never in the mempool. The bid payload (address, amount, nonce, signature) is signed locally and encrypted before being sent on-chain. Public observers see only the deposit (an upper bound) and the ciphertext bytes.

Last-block sniping

Threat: A bidder waits until the last moment to see all other bids, then submits a slightly higher bid.

Defense: Bids are encrypted. There is no information to wait for. Late bidders have no informational advantage over early bidders.

Seller peeking at bids before deadline

Threat: The seller reads bid amounts before the deadline and adjusts their reserve price to squeeze the highest bidder.

Defense: The seller's reserve is also sealed in a CDR vault. It must be written before the deadline and is revealed only at settle, after the bid-reveal condition passes. Neither side sees the other's number until settlement.

Operator peek

Threat: SealedIP (the orchestrator) reads bid amounts before the deadline and acts on that information.

Defense: Threshold cryptography means no single party, including the orchestrator, can decrypt a bid alone. Decryption requires t-of-n validator shares, and validators only publish shares after the on-chain read condition returns true.

Single-validator compromise

Threat: A malicious or compromised validator learns one decryption share and uses it to decrypt early.

Defense: A single share is mathematically insufficient to decrypt a TDH2 ciphertext. The attacker needs t-1 additional shares to combine with theirs.

Timing-only decrypt (deadline without trigger)

Threat: An observer decrypts bids as soon as the clock passes the deadline, before the auction has been officially triggered.

Defense: The AuctionRevealCondition gates validator share publication on BOTH block.timestamp >= deadline AND isTriggered(auctionId) == true. Deadline elapsed alone does not open the reveal condition. See AuctionRevealCondition.

Signature forgery at settle (orchestrator attacks winner slot)

Threat: A malicious orchestrator submits a forged signature in reveals[] to mint a license to a chosen address.

Defense: For each bid, settle() runs eth-signed-prefix ecrecover and checks the recovered address against the on-chain bid.bidder. Forged signatures fail recovery and the bid is skipped. The orchestrator can only CENSOR (omit a valid bid, which triggers refund), never forge a winner.

Amount-exceeds-deposit attack

Threat: A bidder reveals an amount higher than their deposit to win at a price they did not escrow.

Defense: settle() enforces reveal.amount <= slot.deposit. Bids exceeding the deposit are skipped and the deposit is refunded.

Bypassing the sealed reserve

Threat: An orchestrator omits the ReserveReveal or passes a zeroed struct to make the reserve floor disappear.

Defense: If the seller called submitEncryptedReserve, the contract sets reserveHasCiphertext = true. At settle, an empty or invalid ReserveReveal recovers address(0), which does not match the seller, and the call reverts with InvalidReserveReveal. The reserve cannot be skipped.

Double-write of ciphertext

Threat: A bidder writes one ciphertext, observes other bids' deposits, then overwrites with a different ciphertext.

Defense: submitEncryptedBid reverts with CiphertextAlreadyWritten if a ciphertext already exists for the uuid. submitEncryptedReserve similarly reverts with ReserveAlreadyWritten.

Cross-auction replay

Threat: A bid signature from one auction is replayed as a bid in another.

Defense: The signed digest includes auctionId. A signature for auction 5 will not recover correctly when verified against auction 6.

License-mint-without-payment

Threat: Settlement mints a license but the seller payout fails, leaving the contract in an inconsistent state.

Defense: Settlement is atomic. If any transfer or mint fails, the entire transaction reverts. Either everything happens or nothing does.

What SealedIP does NOT defend against

Validator collusion above threshold

Threat: t or more validators collude to decrypt bids before the deadline.

Why we can't defend: This is the central security assumption of any threshold-cryptography scheme. It cannot be fixed with additional cryptography. You are trusting that the CDR validator set does not collude. See CDR network for who operates the set.

Orchestrator censorship

Threat: The orchestrator omits a valid bid from the reveals[] array, preventing that bidder from winning.

Why we can't fully defend: The contract cannot verify that the orchestrator submitted all valid decrypted bids. A censored bid's deposit is refunded (not stolen), so the worst case is that the bidder loses their chance to win, not their funds.

Honest characterization: The orchestrator can only CENSOR, never forge a winner or move funds to a non-winner. Censorship auto-refunds.

CDR reveal-integrity vs. ciphertext

Honest characterization: The contract verifies the seller's signature on the revealed reserve amount, but it does not check that the revealed amount matches what was encrypted in the CDR vault. The same is true for bids. The contract trusts the plaintext produced by CDR threshold decryption plus the bidder/seller signatures. If the CDR network were compromised enough to produce crafted plaintexts, signature verification would still catch amounts that the signer never signed, but amounts the signer DID sign would pass even if the signer is the attacker. This is the CDR trust boundary.

Inference from deposit size

Threat: A bidder's deposit signals an upper bound on their bid.

Why we can't defend: The deposit must be public so the contract can enforce the cap at settle. If you want to obscure your upper bound, over-deposit and accept the overpayment refund at settle.

Operator availability for live settle

Threat: The SealedIP orchestrator goes offline. Triggered auctions sit idle.

Why we can't fully defend: trigger() is permissionless, so anyone can flip state to Triggered. But reading CDR plaintext and calling settle() in practice requires orchestrator infrastructure. Deposits remain safe while the orchestrator is offline, but auctions do not advance. See Orchestrator availability.

Side channels on the bidder's machine

Threat: A bidder's browser or server is compromised, leaking the plaintext bid amount before encryption.

Why we can't defend: The plaintext exists on the bidder's device between signing and encryption. If their machine is compromised, the plaintext is exposed. Browser-level defenses are the bidder's responsibility.

License token misuse downstream

Threat: The winning bidder uses the license in ways the PIL terms do not permit (e.g., commercial use under a non-commercial license).

Why we can't fully defend: PIL terms are enforced by Story Protocol's LicensingModule for explicit on-chain actions. Off-chain usage is outside the contract's reach.

IP misrepresentation

Threat: A seller lists an IP they do not actually own.

Why we can't defend: Story Protocol's registration does not verify real-world ownership. SealedIP inherits this. Buyers should perform real-world due diligence before bidding on high-value listings.

Reading deeper