Marketplace Source Attribution

One challenge for NFT Aggregation platforms is the most gas-efficient method to fill an order is directly through the exchange contract (Seaport, LooksRare, etc). However when doing so, the transaction is indistinguishable from an order that was filled on the marketplace where the order was created (e.g. OpenSea). This leads to significant misreporting of where NFT volume is happening, when looking at on-chain analytics. As an example, around 50% of all Gem transactions are filled directly via Seaport, and completely unattributed to Gem!

To solve this problem, we are working with the NFT community on a standard for attributing trades that is:

  • open
  • on-chain
  • gas-efficient
  • compatible with any exchange

In short, the idea is that aggregation platforms pass their domain name in the calldata of each transaction they fill, so that on-chain analytics tools can parse it and determine who filled the order.

Domain names are used because:

  • They are easy to read
  • They can be visited to learn more
  • Additional metadata (icon, etc) can be pulled from html tags

Version 1

In Version 1, the domain is converted to hex, and surrounded by the delimiter 1f:

ens.vision > 1f656e732e766973696f6e1f
marketplace.truthlabs.co > 1f6d61726b6574706c6163652e74727574686c6162732e636f1f

Example Transaction:
Dune Report Demonstrating Parsing

Version 2

The advantage of Version 1 is that it is completely open, and does not require any "registry" of valid domains. However the downside is that the gas cost grows with the length of the domain (16 gas units per character).

To solve this, we are working on a V2 that uses the first 4 bytes of the domain hash:

bytes4(keccak256("mydomain.com")

This is already live in production on Gem:

gem.xyz > 72db8c0b

Example Dune Query

We will be rolling this out across Reservoir soon, along with tooling for reverse lookups on domain hashes.

Setting custom source metadata

By default Reservoir will automatically create source metadata for every new source that creates or fills an order. However it is possible to overwrite these defaults by setting your own custom source metadata using Reservoir meta tags.

The reservoir:title meta tag should map to a human readable marketplace name. If nothing is provided then the domain is used instead.

<meta property="reservoir:title" content="Reservoir Marketplace" />

Use the reservoir:icon meta tag to override the icon that the reservoir orderbook uses to display your marketplace logo. If nothing is provided then the favicon is used by default. The url can either be relative or absolute.

<meta
  property="reservoir:icon"
  content="https://api.reservoir.tools/redirect/sources/reservoir/logo/v2"
/>

The reservoir:token-url-x meta tag is used to provide a url for the indexer to redirect to the correct token page. It can either be an absolute or a relative url. Replace x with the name of your chain (mainnet, goerli etc) and keep the two required keys (contract and tokenId). These keys are meant to be a placeholder for the indexer to replace when generating the url. This api redirects to the given url: Redirect response to the given source token page

<meta
  property="reservoir:token-url-mainnet"
  content="https://reservoir.market/${contract}/${tokenId}"
/>

<meta
  property="reservoir:token-url-goerli"
  content="https://dev.reservoir.market/${contract}/${tokenId}"
/>

<meta
  property="reservoir:token-url-polygon"
  content="https://polygon.reservoir.market/${contract}/${tokenId}"
/>