Skip to main content

Settling an auction yourself

trigger() and settle() are both permissionless. The SealedIP-operated orchestrator usually handles them, but you don't have to wait — if the deadline has passed and you want the result faster, you can pay gas to close the auction yourself.

When to do this

  • The deadline passed but the orchestrator hasn't triggered yet (rare, but possible if the orchestrator is busy or down).
  • You want immediate finality — you can't move on until the auction is closed.
  • You're bidding on a closing-soon auction and want to settle the moment the deadline hits.

Triggering

After the deadline, the auction detail page shows a Settle auction button in place of "Place sealed bid". Click it.

Your wallet signs one transaction: SealedAuction.trigger(auctionId). Gas varies but is small. The contract:

  • Verifies block.timestamp >= auction.deadline
  • Flips state from Open to Triggered (or ExpiredEmpty if no bids)
  • Emits AuctionTriggered

Triggering is the second gate that opens the AuctionRevealCondition. CDR validators won't publish decryption shares until BOTH conditions are true: block.timestamp >= deadline AND isTriggered(auctionId) == true. So calling trigger is the act that unlocks decryption — not just the passage of time alone.

That's all you need to do. Validators detect the event off-chain and start publishing partial decryption shares to CDR.

What gets revealed at settle

The orchestrator collects CDR plaintext for every bid uuid AND for the seller's reserveUuid, then calls:

settle(auctionId, BidReveal[] reveals, ReserveReveal reserveReveal)

In one transaction, the contract:

  1. Re-verifies every bid signature on-chain (ecrecover, EIP-2 low-s enforced)
  2. Rejects any bid where amount > deposit
  3. Reveals and verifies the sealed reserve: recovers the seller's address from the ReserveReveal signature; if it doesn't match the seller on record, the whole settle reverts with InvalidReserveReveal
  4. Finds the highest valid bid at or above the revealed reserve
  5. Mints the PIL license token to the winner
  6. Transfers the winning WIP amount to the seller
  7. Refunds the winner's overpayment and every losing deposit

All seven steps happen atomically. If anything fails, nothing changes.

If no valid bid clears the revealed reserve, the auction enters ExpiredNoWinner and every deposit is refunded. The license is not minted and the seller receives nothing.

If the seller never sealed a reserve (reserveHasCiphertext == false), the floor defaults to 0 WIP, and settle must be called with a zero-amount ReserveReveal. Any non-zero valid bid clears a zero floor.

Waiting for settle

You don't need to do anything else after triggering. The orchestrator detects the AuctionTriggered event, waits for t-of-n validator shares to arrive for every vault (bids and reserve), reads the plaintext, and calls settle.

In practice this takes anywhere from a few seconds to a few minutes, depending on validator round timing.

If the orchestrator never calls settle() — e.g., it's offline — anyone can construct the reveals from the published shares and call settle themselves. This is much harder than triggering: it requires reading CDR's plaintext for every uuid in the auction (including the reserve uuid) and packing the result as BidReveal[] and ReserveReveal. See Triggering auctions for the operator mechanics.

Why anyone can do it

trigger() has only a deadline gate, not a caller check. This is intentional:

  • The SealedIP team doesn't want to be a liveness bottleneck. If we go down, you can still close auctions.
  • Bidders who know they've won want finality. Letting them trigger themselves removes a wait.
  • Composability: a downstream contract that depends on SealedIP settlement can trigger autonomously.

Nothing changes in the contract behavior whether the trigger comes from us, the seller, the winning bidder, or a random observer. The auction settles identically.

What you pay

You pay only the gas for the trigger transaction. The orchestrator (or whoever calls settle) pays the gas for the close-out, which scales linearly with the number of bids.

If you also call settle yourself, you pay that gas too. For an auction with many bids this can be expensive — settle is the protocol's most gas-heavy operation.

What you don't get

Calling trigger doesn't give you any special treatment in the auction. Your bid (if any) goes through the same verification path as everyone else's. There's no "first to trigger" prize.

When triggering fails

trigger() reverts with:

In both cases the wallet shows a humanized error and refunds the gas reservation (you still pay the failed-tx base cost).