ContractsListings

Listings

Contracts/src/contracts/Listings.sol

Owns the liquid + dutch + floor listing lifecycle. Floor listings (format = NONE) are created implicitly by the Locker on deposit/swap; liquid and dutch listings are first-class objects created via createListings.

Listings inherits TokenEscrow, so listing refunds, sale proceeds, and unaccrued tax all share the same escrow surface as NFTXV4Hook AMM fees.

State views

FunctionReturns
locker()The owning ILocker
listings(_collection, _tokenId)(owner, created, duration, floorMultiple)
listingCount(_collection)Active liquid + dutch listings count
defaultTaxCalculator()Default ITaxCalculator
collectionTaxCalculator(_collection)Per-collection override (zero = use default)
taxCalculator(_collection)Effective tax calc after override-or-default fallback
defaultListingConfig()(maxFloorMultiple, minLiquid, maxLiquid, minDutch, maxDutch, liquidDutchDuration) defaults
collectionListingConfig(_collection)Raw per-collection override
listingConfig(_collection)Effective config after override-or-default fallback
getListingType(_collection, _listing)Resolves Enums.ListingType (NONE, LIQUID, DUTCH)
getListingPrice(_collection, _tokenId)(isAvailable_, price_) — current fillable price
getListingTaxRequired(_listing, _collection)Tax owed up-front for a hypothetical listing

Public surface

Create / fill

FunctionCallerDescription
createListings(_createListings)Owner of NFTsMint one or many listings; all share their CreateListing.listing config
fillListings(params)BuyerAtomic group fill across owners
relist(_listing, _payTaxWithEscrow)BuyerBuy + re-list in one tx

Modify / cancel

FunctionCallerDescription
modifyListings(_collection, _modifyListings, _payTaxWithEscrow)Listing ownerUpdate (duration, floorMultiple) per tokenId; returns (taxRequired_, refund_)
cancelListings(_collection, _tokenIds, _payTaxWithEscrow)Listing ownerCancel — refund the unaccrued tax
transferOwnership(_collection, _tokenId, _newOwner)Listing ownerHand over without changing economics

Tax / config (admin)

FunctionDescription
setDefaultTaxCalculator(_taxCalculator)Default tax calc
setCollectionTaxCalculator(_collection, _taxCalculator)Per-collection override (zero clears)
setDefaultListingConfig(_config)Default ListingConfig
setCollectionListingConfig(_collection, _config)Per-collection override

Structs

struct Listing {
  address payable owner;
  uint40 created;
  uint32 duration;
  uint16 floorMultiple;
}
 
struct CreateListing {
  address collection;
  uint[] tokenIds;
  Listing listing;
}
 
struct ModifyListing {
  uint tokenId;
  uint32 duration;
  uint16 floorMultiple;
}
 
struct ListingConfig {
  uint16 maxFloorMultiple;     // 100 = 1.00x
  uint32 minLiquidDuration;
  uint32 maxLiquidDuration;
  uint32 minDutchDuration;
  uint32 maxDutchDuration;
  uint32 liquidDutchDuration;  // tail decay applied to expired liquid
}
 
struct FillListingsParams {
  address collection;
  uint[][] tokenIdsOut;
  address recipient;
  uint maxSpend;
}

ListingConfig.maxFloorMultiple == 0 is the sentinel value the contract uses to mean “no per-collection override” — any valid config has maxFloorMultiple > 100.

Errors

ErrorWhere
LockerIsZeroAddressconstructor
TaxCalculatorIsZeroAddressconstructor
InvalidListingConfigsetDefaultListingConfig / setCollectionListingConfig cross-field violations
InsufficientTax(taxPaid, taxRequired)create / modify
InvalidFloorMultiple(_floorMultiple, _expectedFloorMultiple)mismatch on relist preflight
LockerIsNotTokenHolderNFT not in the Locker
CollectionNotInitializedpool not bootstrapped
ListingOwnerIsZero, NewOwnerIsZeroinvariants
FloorMultipleMustBeAbove100(_floorMultiple)floor not allowed as a listing
FloorMultipleExceedsMax(_floorMultiple, _maxFloorMultiple)over per-collection cap
ListingDurationBelowMin(...) / ListingDurationExceedsMax(...)outside config bands
InvalidListingTypeduration falls between dutch and liquid bands
CallerIsNotOwner(_expectedCaller)mutation attempted by non-owner
CannotCancelListingTypetried to cancel NONE
ListingNotAvailableexpired beyond dutch tail / cancelled / filled
InvalidCollection, InvalidOwner, CallerIsAlreadyOwnerargument invariants
Paused()listings paused
FillCostExceedsMaxSpend(totalCost, maxSpend)sandwich guard tripped on fill
RelistAcceptsSingleTokenOnlypassed >1 tokenId to relist

Events

EventTrigger
ListingsCreated(_collection, _tokenIds, _listing, _listingType, _tokensRequired, _taxRequired, _sender)createListings
ListingRelisted(_collection, _tokenId, _listing)relist
ListingsFilled(_collection, _tokenIds, _recipient)fillListings
ListingTransferred(_collection, _tokenId, _owner, _newOwner)transferOwnership
ListingsCancelled(_collection, _tokenIds)cancelListings
ListingExtended(_collection, _tokenId, _oldDuration, _newDuration)modifyListings (duration changed)
ListingFloorMultipleUpdated(_collection, _tokenId, _oldFM, _newFM)modifyListings (multiple changed)
ListingFeeCaptured(_collection, _tokenId, _amount)tax accrual
DefaultTaxCalculatorUpdated(_taxCalculator)admin
CollectionTaxCalculatorUpdated(_collection, _taxCalculator)admin
DefaultListingConfigUpdated(_config)admin
CollectionListingConfigUpdated(_collection, _config)admin

Inherited surface

  • TokenEscrowwithdraw(_recipient, _token, _amount), balances(_recipient, _token), Deposit / Withdrawal events.
  • Pausable, Ownable, ReentrancyGuard.