Open listings
List a whole lot at one price for any buyer. One native ticket makes sure exactly one buyer pays.
How do you let anyone buy a lot, and guarantee that only one of them pays?
In development
Open listings are built on a development track and are not switched on for mainnet yet. Today's protocol sells to a named buyer.
An open listing replaces the named buyer with anyone. The seller lists a whole lot at one total price; the first valid purchase takes it. The problem to solve is the race: two buyers must never both pay for one lot.
The race, step by step
- 01 / 05
The seller lists a whole lot
One signed LIST reserves 50,000 GLYF at a total price of 120 QTC. Nothing is escrowed and listing costs no Qlyphs fee. The listing points to a ticket: a native account address that does not exist yet.
- 02 / 05
Two buyers click Buy
Each buyer’s wallet signs the same three-part atomic batch: create the ticket, pay the seller 120 QTC, pay the 1% fee. Both transactions reach the chain.
- 03 / 05
The first one creates the ticket
Buyer A’s batch lands first. The ticket is created, both payments go through, and QLYP credits the reserved 50,000 GLYF to Buyer A.
- 04 / 05
The second one fails before paying
A ticket can be created only once. Buyer B’s first step fails, so the atomic batch stops and neither payment runs. Buyer B loses only the network fee.
- 05 / 05
The trade-off, stated plainly
Anyone can create the ticket, so anyone can end a listing without buying it, at the cost of a transaction. The lot then goes back to the seller. Nobody pays twice, but a listing can be griefed. Buyers take the whole lot; there is no partial fill or expiry.
The ticket
The ticket is a native Quantus multisig address, fixed at listing time from the seller, the hash of the block that contains the listing and the listing's position in it:
ticket = create_multisig(sort([seller, listing_block_hash]), 2, listing_index)
buy = batch_all([ create(ticket), pay(payout, price), pay(fee account, 1%) ])Quantus lets that address be created exactly once. That single native property is the lock: the second creation fails, and because the purchase is one atomic batch, a losing buyer's payments never run. Whoever signed the successful canonical purchase receives the lot.
Why derive the ticket from the listing block?
The ticket must not exist before the listing. Otherwise someone could create it in advance and kill the listing the moment it appears.
Nobody knows a block's hash before the block exists. Deriving the ticket from the listing's block hash and its position in that block makes it unique to this listing and impossible to create earlier.
Everyone can compute it afterwards. Buyers, wallets and indexers all derive the same address from public data, so every buyer races for the same single ticket.
Terms
- Whole lot, one price. No partial fills; a buyer takes everything listed.
- No escrow, no listing fee. Units are reserved in the QLYP ledger; QTC goes straight from the buyer to the seller's payout account. The buyer pays the 1% sale fee.
- No expiry. A listing stays open until it is bought or the seller cancels it.
- Safety over liveness. Any use of the ticket ends the listing. If someone creates it without buying, the lot simply returns to the seller: nobody pays for nothing, but a listing can be interrupted by anyone willing to pay a transaction.
An API check alone could not stop two buyers paying for one lot. The native one-use ticket does, for purchases built by a conforming wallet on finalized state.