Product Marketplace

The xendune marketplace supports four product types, each with dedicated escrow templates deployed via ProductFactory using EIP-1167 clones. Up to 24 products per page (MAX_PAGE_SIZE = 24).

Product Types

Physical Products (PhysicalProductTemplate) — 3% fee

For tangible goods requiring logistics delivery. Escrow flow includes:

Virtual Products (VirtualProductTemplate) — 3% fee

For digital goods (game keys, software licenses, digital content, etc.). Similar to physical products but with these differences:

Services (ServiceProductTemplate) — 5% fee

For local offline services. Key differences:

WantToBuy (WantToBuyTemplate) — 3% fee

Buyer publishes a demand; seller responds and fulfills:

Creating Products

Products are created through ProductFactory:

  1. Keywords must be pre-approved by admin/customer service
  2. Seller must not be blacklisted
  3. Active product limit: no deposit — max 1; with deposit — max 5 (maxProductsWithoutDeposit / maxProductsWithDeposit, adjustable by Owner)

The factory clones the corresponding template, calls initialize(), and registers the product in all indexes.

Multi-Order Support

Each product contract supports multiple concurrent orders. Orders are identified by unique bytes16 orderId generated as:

keccak256(abi.encodePacked(contractAddress, buyer, timestamp, nonce))

This enables a single product listing to handle multiple buyers simultaneously without deploying new contracts per transaction.

Order Lifecycle

Physical/Virtual Products

Placed → Shipped/Delivered → Completed
   ↓            ↓
Cancelled  In Arbitration → Resolved

Services

Placed → Service In Progress → Completed
   ↓             ↓
Cancelled   In Arbitration → Resolved

Specs and Pricing

Physical and virtual products use Spec structs:

Service products use ServiceItem:

Sellers can update specs/service items and product info when no orders are in progress.

Auto-Confirm

Physical and virtual products have auto-confirm mechanisms:

Product Delisting

Products can be delisted (removed from active listings) three ways:

  1. Seller voluntary delisting: delistProduct() — requires no orders in progress
  2. Admin forced delisting: adminDelistProduct() — requires no orders in progress
  3. Factory forced delisting: delistByFactory() — called during zombie deposit reclamation

After delisting, the product contract remains on-chain for historical queries but no longer accepts new orders.

Settlement

When an order completes, fees are distributed to the seller's invite chain via InviteRegistry (L1 gets 20%, L2 gets 10% of the fee), with the remainder split to the platform via PlatformFeeSplitter. The net amount is then transferred to the seller. If any transfer fails, the amount is stored in pendingWithdrawals[recipient] for later claim via claimPending().