Auction
Single-item auction with intent-based bidding. Seller mints NFT directly to the winning bidder during the accept window.
Category: Token Types
Summary
Required standards: ["Auction"]
1 token ID (the auctioned item)
2 collection-level approvals: mint-to-winner (combines mint + accept), burn (cleanup)
Mint-to-winner: seller mints NFT directly to winning bidder during accept window (bidDeadline β bidDeadline + acceptWindow)
No separate mint-at-creation step β token doesn't exist until seller accepts a bid
Burn: anyone can burn token to burn address (permanent cleanup)
Bidding via user-level outgoing approval intents (not collection approvals)
Bids must have transferTimes valid through end of accept window (not just bid deadline)
initiatedByListId on mint-to-winner = seller address (only seller can accept)
maxNumTransfers = 1 on all approvals (one-shot)
overridesToIncomingApprovals: false on mint-to-winner (bidder's incoming approval handles payment)
Burn approval has NO override flags β relies on defaultBalances autoApproveSelfInitiatedOutgoingTransfers + burn destination
noForcefulPostMintTransfers: true in invariants (permanently locks out forceful transfers post-mint)
After settlement, the mint-to-winner approval is auto-deleted via afterOneUse β protocol validators treat a missing mint-to-winner as a valid post-settlement state, not an error
All permissions frozen after creation
DON'T use coinTransfers on collection approvals β payment happens via intent matching
DON'T set initiatedByListId to "All" on mint-to-winner β must be seller
DON'T set transferTimes to forever β must be bounded to accept window
DON'T put override flags on the burn approval β auction has noForcefulPostMintTransfers: true, so non-mint override flags would be invariant violations
DO use autoDeletionOptions.afterOneUse: true on mint-to-winner
Instructions
Auction Configuration
Mental Model
A single-item auction where the seller creates a collection, bidders place intent-based bids, and the seller mints the NFT directly to the winning bidder during the accept window. There is no separate mint-then-transfer flow β mint + accept happen in one action. The collection has NO coinTransfers β payment is handled entirely through the bidder's user-level approval (intent matching).
Collection Structure
Token ID 1 = The auctioned item
Standard: "Auction"
validTokenIds: [{ start: "1", end: "1" }]
invariants: `{ noCustomOwnershipTimes: true, maxSupplyPerId: "0", noForcefulPostMintTransfers: true, disablePoolCreation: true }`
`noForcefulPostMintTransfers: true` locks the collection so no non-mint approval can ever use `overridesFromOutgoingApprovals` or `overridesToIncomingApprovals` β the burn approval below relies on `defaultBalances` auto-approve flags instead
All permissions frozen after creation
Bidding Mechanism
Bidders set user-level outgoing approvals on their own accounts that say "I will pay X coins for token 1 from this collection." The seller then accepts the best bid by minting the token directly to the winning bidder during the accept window. The bidder's outgoing approval handles the coin payment side via intent matching.
Bids must have transferTimes that stay valid through the END of the accept window (not just the bid deadline), so the seller can match them during the entire accept period.
2 Approvals
1. Mint-to-Winner (seller mints NFT directly to winning bidder during accept window)
```json { "approvalId": "auction-mint-to-winner", "fromListId": "Mint", "toListId": "All", "initiatedByListId": "<SELLER_ADDRESS>", "tokenIds": [{ "start": "1", "end": "1" }], "transferTimes": [{ "start": "<BID_DEADLINE>", "end": "<BID_DEADLINE + ACCEPT_WINDOW>" }], "approvalCriteria": { "overridesFromOutgoingApprovals": true, "overridesToIncomingApprovals": false, "coinTransfers": [], "predeterminedBalances": { "incrementedBalances": { "startBalances": [{ "amount": "1", "tokenIds": [{ "start": "1", "end": "1" }], "ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }] }] }, "orderCalculationMethod": { "useOverallNumTransfers": true } }, "maxNumTransfers": { "overallMaxNumTransfers": "1" }, "autoDeletionOptions": { "afterOneUse": true, "afterOverallMaxNumTransfers": true } } } ```
CRITICAL: `overridesToIncomingApprovals: false` β the bidder's incoming approval (intent) must be checked so the coin payment side executes. `transferTimes` are bounded to the accept window only β the seller cannot mint before the bid deadline. `toListId: "All"` allows minting to any address (the winning bidder).
2. Burn (cleanup β anyone can burn the token)
```json { "approvalId": "auction-burn", "fromListId": "!Mint", "toListId": "<BURN_ADDRESS>", "initiatedByListId": "All", "tokenIds": [{ "start": "1", "end": "1" }], "transferTimes": [{ "start": "1", "end": "18446744073709551615" }] } ```
No `approvalCriteria` overrides: because the invariants lock `noForcefulPostMintTransfers: true`, the burn approval MUST NOT set `overridesFromOutgoingApprovals` or `overridesToIncomingApprovals`. It relies on `defaultBalances.autoApproveSelfInitiatedOutgoingTransfers: true` for the outgoing side and on the burn destination for the incoming side.
Auction Flow
Create: Seller creates auction collection with 2 approvals. No token is minted yet.
Bid: Bidders place intent-based bids (user-level outgoing approvals with coin payment offers). Bids must have transferTimes valid through end of accept window.
Accept: After bid deadline, seller mints token 1 directly to the winning bidder's address. The bidder's outgoing approval triggers coin payment via intent matching. One action: mint + payment.
Cleanup: If unsold, burn approval allows cleanup.
Creation Flow (Tool Calls)
`set_valid_token_ids` β set [{ start: "1", end: "1" }]
`set_standards` β set ["Auction"]
`set_invariants` β set `{ noCustomOwnershipTimes: true, maxSupplyPerId: "0", noForcefulPostMintTransfers: true, disablePoolCreation: true }`
`add_approval` x2 β mint-to-winner, burn
`set_collection_metadata` β auction title, description, image
`set_token_metadata` β token 1 metadata (the item being auctioned)
`set_permissions` β preset "fully-immutable"
`validate_transaction` β verify structure
`simulate_transaction` β dry run
Common Mistakes
DON'T add coinTransfers to collection approvals β payment flows through intent matching, not collection-level coin transfers
DON'T set initiatedByListId to "All" on mint-to-winner β only the seller can accept bids
DON'T set transferTimes to forever β MUST be bounded to accept window (bidDeadline β bidDeadline + acceptWindow)
DON'T set overridesToIncomingApprovals to true on mint-to-winner β must be false so the bidder's incoming approval (payment intent) is checked
DON'T add override flags to the burn approval β the invariant `noForcefulPostMintTransfers: true` rejects `overridesFromOutgoingApprovals` or `overridesToIncomingApprovals` on any non-mint approval
DON'T worry if the mint-to-winner approval is absent after settlement β `autoDeletionOptions.afterOneUse: true` removes it after the first successful mint, and the protocol validator accepts that as a valid post-settlement state
DON'T create a separate mint-to-seller approval β the token should not exist until the seller accepts a bid
DON'T forget autoDeletionOptions on mint-to-winner β without afterOneUse: true, the seller could mint to multiple bidders
DON'T forget that bids must have transferTimes valid through the END of the accept window, not just the bid deadline
Last updated