Skip to main content

State machine

The SealedAuction contract stores each auction's state as a uint8 enum field. The values are:

NumericNameUI label
0OpenOpen or Closing if past deadline
1TriggeredSettling
2SettledSettled
3ExpiredNoWinnerEnded
4ExpiredEmptyEnded

When reading auctions off-chain via auctions(uint256), the state is the 7th field in the returned tuple (index 6). The full tuple is: (address seller, address ipId, uint256 licenseTermsId, uint32 reserveUuid, bool reserveHasCiphertext, uint64 deadline, uint8 state, uint16 bidCount). See SealedAuction.auctions.

Distinguishing "open with countdown" from "open past deadline"

The contract only stores Open for both sub-states. The UI distinguishes them using the deadline:

const isOpen = state === 'Open' && Number(deadline) > now
const isClosing = state === 'Open' && Number(deadline) <= now

The Closing pill on the marketplace UI is not a separate on-chain state. It is a derived label that means "the contract is Open but the deadline has passed and anyone can trigger".

Allowed transitions

Terminal states (Settled, ExpiredNoWinner, ExpiredEmpty) are immutable. Once an auction reaches a terminal state, no further functions on it succeed.

Permissions per state

StatecreateAuctionsubmitEncryptedReserveallocateBidSlotsubmitEncryptedBidtriggersettle
(does not exist)seller ✓
Open (countdown)seller ✓anyone ✓slot owner ✓
Open (past deadline)revertsrevertsrevertsanyone ✓
Triggeredrevertsrevertsrevertsrevertsanyone ✓
Settledrevertsrevertsrevertsrevertsreverts
ExpiredNoWinnerrevertsrevertsrevertsrevertsreverts
ExpiredEmptyrevertsrevertsrevertsrevertsreverts

createAuction always allocates a new auctionId, so it is not gated by an existing auction's state.

settle() is technically permissionless (no caller check), but the caller must supply correctly-decrypted reveals. In practice only the CDR orchestrator has the means to produce reveals at scale.

trigger() requires BOTH gates

trigger() has no caller check beyond the deadline gate. Any address can pay gas to call it. This is intentional: if the SealedIP-operated orchestrator goes down, anyone can step in.

Calling trigger() is required for a second reason beyond convenience: it sets the second gate on AuctionRevealCondition. Validators will not publish decryption shares until AuctionRevealCondition.checkReadCondition returns true, which requires:

  1. block.timestamp >= deadline, AND
  2. SealedAuction.isTriggered(auctionId) == true

Neither the passage of time alone nor an explicit trigger call alone is sufficient. Both must hold. This prevents CDR validators from being front-run by a premature trigger.

Per-state behavior summary

Open (countdown running)

The seller can:

  • Seal the reserve (submitEncryptedReserve, once)

Bidders can:

  • Allocate new slots (allocateBidSlot)
  • Submit ciphertext for slots they own (submitEncryptedBid)

Nobody can:

  • Trigger the auction (deadline not reached)
  • Settle the auction (state is not Triggered)

Open (past deadline)

Nobody can:

  • Allocate new slots (BiddingClosed)
  • Submit ciphertext (BiddingClosed)
  • Submit reserve ciphertext (BiddingClosed)

Anyone can:

  • Trigger the auction (trigger() succeeds; state goes to Triggered or ExpiredEmpty)

Triggered

Nobody can:

  • Allocate slots, submit ciphertext, or re-trigger

Anyone with valid reveals can:

  • Call settle() (state goes to Settled or ExpiredNoWinner)

Validators are off-chain, publishing shares to the CDR contract for all vaults registered in this auction (bid vaults plus the reserve vault).

Settled / ExpiredNoWinner / ExpiredEmpty

Nothing further can be done on the auction. It is history.

The PIL license token (in Settled) lives on. Its provenance is fixed and points to this auction's auctionId and licenseTermsId.

Detecting state changes

For real-time apps, watch these events:

EventMarks transition into
AuctionCreatedOpen
EncryptedReserveSubmitted(no transition; indicates reserve sealed)
BidSlotAllocated(no transition; indicates bidder activity)
EncryptedBidSubmitted(no transition; indicates bid sealed)
AuctionTriggeredTriggered
AuctionSettledSettled
AuctionExpiredNoWinnerExpiredNoWinner
AuctionExpiredEmptyExpiredEmpty

See Events reference for full signatures and argument ordering.