> For the complete documentation index, see [llms.txt](https://docs-v4.nftx.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-v4.nftx.io/contracts/listings.md).

# Listings

`Listings` is NFTX v4's self-assessed listing system. A seller lists a non-floor item at a chosen **floor multiple** and duration; the listing accrues **tax upfront** based on that price and duration, priced and paid in the collection's ERC-20. Cancelling or shortening a listing refunds the unused tax pro-rata. Collections can override the defaults for both the [tax calculator](/contracts/tax-calculator.md) and the listing config.

Signatures and descriptions below come from the `IListings` interface. Two listing shapes exist — **liquid** and **Dutch** — and an expired liquid listing automatically decays through a trailing Dutch phase (see [`getListingType`](#getlistingtype)).

## Data structures

### `Listing`

The stored state of a single listing.

| Field           | Type              | Description                                                                   |
| --------------- | ----------------- | ----------------------------------------------------------------------------- |
| `owner`         | `address payable` | Address that owns and can manage the listing                                  |
| `created`       | `uint40`          | Timestamp of listing creation                                                 |
| `duration`      | `uint32`          | Prepaid duration of the listing, in seconds                                   |
| `floorMultiple` | `uint16`          | Price as a multiple of the floor token, to two decimal places (`100` = 1.00x) |

### `CreateListing`

The input to [`createListings`](#createlistings) and [`relist`](#relist).

| Field        | Type      | Description                                           |
| ------------ | --------- | ----------------------------------------------------- |
| `collection` | `address` | The collection address of the assets being listed     |
| `tokenIds`   | `uint[]`  | The token IDs being listed                            |
| `listing`    | `Listing` | The `Listing` data defining type, duration, and price |

### `ListingConfig`

Per-collection (or default) bounds that constrain what listings are allowed.

| Field                 | Type     | Description                                                                                                                      |
| --------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `maxFloorMultiple`    | `uint16` | Inclusive upper bound on `floorMultiple`; two-decimal precision (`100` = 1.00x)                                                  |
| `minLiquidDuration`   | `uint32` | Inclusive lower bound on liquid-listing duration                                                                                 |
| `maxLiquidDuration`   | `uint32` | Inclusive upper bound on liquid-listing duration                                                                                 |
| `minDutchDuration`    | `uint32` | Inclusive lower bound on Dutch-listing duration                                                                                  |
| `maxDutchDuration`    | `uint32` | Inclusive upper bound on Dutch-listing duration; must be strictly less than `minLiquidDuration` so the type can be discriminated |
| `liquidDutchDuration` | `uint32` | Length of the trailing Dutch decay applied to an expired liquid listing                                                          |

### `FillListingsParams`

The input to [`fillListings`](#filllistings).

| Field         | Type       | Description                                                                                                                                                                                                                                                                                                                                                                       |
| ------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `collection`  | `address`  | The collection of the tokens being filled                                                                                                                                                                                                                                                                                                                                         |
| `tokenIdsOut` | `uint[][]` | The token IDs being filled, grouped by owner (for gas efficiency)                                                                                                                                                                                                                                                                                                                 |
| `recipient`   | `address`  | The address to receive the NFTs                                                                                                                                                                                                                                                                                                                                                   |
| `maxSpend`    | `uint`     | Hard cap (in collection-token units) on the total buyer spend — the premium routed to owners plus the floor-equivalent burned. Excludes the protocol fill fee (funded from sellers' prepaid tax). A non-zero value protects against front-running: if owners raise prices between simulation and execution, the fill reverts with `FillCostExceedsMaxSpend`. Pass `0` to opt out. |

## Creating and managing listings

### `createListings`

Creates one or more listings. Each token's tax is calculated and prepaid from the caller's funds; the NFTs are held in the Locker and the caller receives one collection token per NFT, minus tax.

```solidity
function createListings(CreateListing[] calldata _createListings) external;
```

**Access:** `nonReentrant`, Locker not paused. Reverts with `InsufficientTax` if the tokens received don't cover the required tax; validates each collection's config bounds; emits `ListingsCreated`.

| Parameter         | Type              | Description                           |
| ----------------- | ----------------- | ------------------------------------- |
| `_createListings` | `CreateListing[]` | Array of listing structures to create |

**Returns:** None.

### `modifyListings`

Changes the duration or price of existing **liquid** listings. Additional tax is required for a longer/higher listing, or tax is refunded for a shorter/lower one; any refund is applied to the new tax first, for gas savings.

```solidity
function modifyListings(address _collection, ModifyListing[] calldata _modifyListings, bool _payTaxWithEscrow) external returns (uint taxRequired_, uint refund_);
```

**Access:** `nonReentrant`, Locker not paused. Caller must be the listing owner; only liquid listings can be modified.

| Parameter           | Type              | Description                                                       |
| ------------------- | ----------------- | ----------------------------------------------------------------- |
| `_collection`       | `address`         | The collection address of the listing                             |
| `_modifyListings`   | `ModifyListing[]` | The listings to modify (per-token `duration` and `floorMultiple`) |
| `_payTaxWithEscrow` | `bool`            | Whether tax should be paid from the caller's escrow balance       |

| Return         | Type   | Description                                           |
| -------------- | ------ | ----------------------------------------------------- |
| `taxRequired_` | `uint` | The collection tokens required to modify the listings |
| `refund_`      | `uint` | The collection tokens refunded to the owner           |

### `cancelListings`

Cancels liquid listings, returning each NFT for one equivalent collection token and refunding any remaining prepaid tax.

```solidity
function cancelListings(address _collection, uint[] calldata _tokenIds, bool _payTaxWithEscrow) external;
```

**Access:** `nonReentrant`, Locker not paused. Caller must be the listing owner; only liquid listings can be cancelled (not Dutch or expired ones).

| Parameter           | Type      | Description                            |
| ------------------- | --------- | -------------------------------------- |
| `_collection`       | `address` | The collection address of the listing  |
| `_tokenIds`         | `uint[]`  | The token IDs to cancel                |
| `_payTaxWithEscrow` | `bool`    | Whether tax should be paid from escrow |

**Returns:** None.

### `relist`

Buys out an existing listing and immediately re-lists that single token with new parameters — the mechanism behind permissionless re-pricing. The caller cannot be the current owner, who is paid any premium as the old listing is filled.

```solidity
function relist(CreateListing calldata _listing, bool _payTaxWithEscrow) external;
```

**Access:** `nonReentrant`, Locker not paused. Accepts a single-token payload only (reverts `RelistAcceptsSingleTokenOnly` otherwise); emits `ListingRelisted`.

| Parameter           | Type            | Description                                         |
| ------------------- | --------------- | --------------------------------------------------- |
| `_listing`          | `CreateListing` | The new listing (must contain exactly one token ID) |
| `_payTaxWithEscrow` | `bool`          | Whether tax should be paid from escrow              |

**Returns:** None.

### `transferOwnership`

Transfers ownership of a listing to another address.

```solidity
function transferOwnership(address _collection, uint _tokenId, address payable _newOwner) external;
```

**Access:** `nonReentrant`, Locker not paused. Caller must be the listing owner; reverts with `NewOwnerIsZero` on the zero address.

| Parameter     | Type              | Description                           |
| ------------- | ----------------- | ------------------------------------- |
| `_collection` | `address`         | The collection address of the listing |
| `_tokenId`    | `uint`            | The tokenId of the listing            |
| `_newOwner`   | `address payable` | The new owner of the listing          |

**Returns:** None.

### `fillListings`

Buys listed NFTs using collection tokens. Token IDs are grouped by owner for gas efficiency. The buyer pays the premium to owners plus the floor-equivalent burned, capped by `maxSpend`; the protocol fill fee comes out of sellers' prepaid tax, not the buyer.

```solidity
function fillListings(FillListingsParams calldata params) external returns (uint totalBurn_);
```

**Access:** `nonReentrant`, Locker not paused. Emits `ListingsFilled`.

| Parameter | Type                 | Description                                                               |
| --------- | -------------------- | ------------------------------------------------------------------------- |
| `params`  | `FillListingsParams` | The fill parameters (collection, grouped token IDs, recipient, max spend) |

| Return       | Type   | Description                                                           |
| ------------ | ------ | --------------------------------------------------------------------- |
| `totalBurn_` | `uint` | The total collection tokens burned (floor equivalent, `1e18` per NFT) |

## Pricing and views

### `getListingPrice`

Returns whether a token can currently be bought from NFTX and its price (in collection-token units, where `1 ether` = 1.0x floor). Dutch listings apply a linear discount over their duration; expired liquid listings enter the trailing Dutch decay.

```solidity
function getListingPrice(address _collection, uint _tokenId) external view returns (bool isAvailable_, uint price_);
```

| Parameter     | Type      | Description                   |
| ------------- | --------- | ----------------------------- |
| `_collection` | `address` | The collection of the listing |
| `_tokenId`    | `uint`    | The token ID of the listing   |

| Return         | Type   | Description                                |
| -------------- | ------ | ------------------------------------------ |
| `isAvailable_` | `bool` | Whether the token is available to purchase |
| `price_`       | `uint` | The price in collection-token terms        |

### `getListingType`

Classifies a listing as `DUTCH`, `LIQUID`, or `NONE`, using the resolved `ListingConfig` for the collection (so per-collection overrides apply here too).

```solidity
function getListingType(address _collection, Listing memory _listing) external view returns (Enums.ListingType);
```

| Parameter     | Type      | Description                   |
| ------------- | --------- | ----------------------------- |
| `_collection` | `address` | The collection of the listing |
| `_listing`    | `Listing` | The listing to classify       |

| Return    | Type                | Description                  |
| --------- | ------------------- | ---------------------------- |
| (unnamed) | `Enums.ListingType` | `DUTCH`, `LIQUID`, or `NONE` |

### `getListingTaxRequired`

Calculates the tax needed to create a listing, validating against a complete `Listing` struct rather than individual parameters. Delegates to the collection's effective [tax calculator](/contracts/tax-calculator.md).

```solidity
function getListingTaxRequired(Listing memory _listing, address _collection) external view returns (uint taxRequired_);
```

| Parameter     | Type      | Description                      |
| ------------- | --------- | -------------------------------- |
| `_listing`    | `Listing` | The listing to price the tax for |
| `_collection` | `address` | The collection of the listing    |

| Return         | Type   | Description                            |
| -------------- | ------ | -------------------------------------- |
| `taxRequired_` | `uint` | The tax required to create the listing |

### Other views

| Function                                                                | Returns                  | Description                                                         |
| ----------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------- |
| `locker()`                                                              | `ILocker`                | The Locker this Listings contract is bound to                       |
| `listings(address _collection, uint _tokenId)`                          | `Listing`                | The stored listing for a token                                      |
| `listingCount(address _collection)`                                     | `uint`                   | Count of open listings for a collection                             |
| `listingConfig(address _collection)`                                    | `ListingConfig`          | The effective config (override if set, else default)                |
| `taxCalculator(address _collection)`                                    | `ITaxCalculator`         | The effective tax calculator (override if set, else default)        |
| `defaultListingConfig()` / `defaultTaxCalculator()`                     | tuple / `ITaxCalculator` | The protocol-wide defaults                                          |
| `collectionListingConfig(address)` / `collectionTaxCalculator(address)` | tuple / `ITaxCalculator` | The raw per-collection override (zero/all-zero means "use default") |

## Configuration (owner only)

These setters are `onlyOwner`.

```solidity
function setDefaultTaxCalculator(address _taxCalculator) external;
function setCollectionTaxCalculator(address _collection, address _taxCalculator) external;
function setDefaultListingConfig(ListingConfig calldata _config) external;
function setCollectionListingConfig(address _collection, ListingConfig calldata _config) external;
```

| Function                     | Parameters                                              | Description                                                                                                                           |
| ---------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `setDefaultTaxCalculator`    | `_taxCalculator` (`address`)                            | Sets the protocol-wide default calculator (reverts on the zero address)                                                               |
| `setCollectionTaxCalculator` | `_collection` (`address`), `_taxCalculator` (`address`) | Sets a per-collection override; pass `address(0)` to clear it and inherit the default                                                 |
| `setDefaultListingConfig`    | `_config` (`ListingConfig`)                             | Sets the default config; validated for cross-field invariants (e.g. `maxDutchDuration < minLiquidDuration`, `maxFloorMultiple > 100`) |
| `setCollectionListingConfig` | `_collection` (`address`), `_config` (`ListingConfig`)  | Sets a per-collection override; pass an all-zero struct (`maxFloorMultiple == 0`) to clear it                                         |
