High level overview

Custom pools in Caviar are a flexible and customizable trading environment for non-fungible tokens (NFTs) that offer advanced features and parameters tailored to the specific requirements of liquidity providers and traders. In contrast to shared pools, custom pools enable users to create unique liquidity pools with additional control and optimization options.


The factory contract allows users to create and initialize new custom pools that are minimal proxies which point to a reference implementation. It is responsible for issuing NFTs that represent ownership of each custom pool. All protocol fees accrue to the factory contract and can be withdrawn by the protocol admin. Initially the protocol fee rate will be set to be 0% however it may be increased in the future, with advanced notice.


The private pool contract contains all of the core logic for custom pools. It allows users to set concentrated liquidity, custom fee rates, NFT weightings, fixed change/flashloan fee rates, and stolen NFT filtering. Traders can buy, sell, and change NFTs for other NFTs within the pool.

Concentrated liquidity:

Concentrated liquidity is achieved through the use of virtual reserves. Each swap uses the xy=k invariant. A user can set the "x" and "y" reserves to be whatever they want. For example they may deposit 1 ETH and 2 NFTs and set the "x" virtual reserve to be 2 ETH and the "y" virtual reserve to be 4 NFTs. Thereby concentrating their deposited liquidity by 2x. This allows for greater capital efficiency and enables liquidity to be deployed within fixed price ranges.

Custom fee rates:

Users can set the fee rate to be whatever value that they want. This allows liquidity providers to tailor their pools depending on the current volatility of the market and how much value they want to capture on each trade.

NFT weightings:

It's possible to set an opinionated weight of each NFT in a collection in the custom pool. For example, an LP could set the weight of token #5 to be 2.3 and the weight of token #1 to be 1.0. Token #5 will be worth 2.3x the amount of token #1 when swapping in the pool. These weights are stored as a merkle root. If no merkle root is set then it's assumed that the weight of each NFT is 1.0.

Change/Flashloan fees:

When a user takes out a flashloan or changes one NFT for another in the pool, they pay a fixed fee that is defined by the custom pool owner.

Stolen NFT filtering:

If an LP has enabled stolen NFT filtering, then each time a user sells or attempts to change one NFT for another, they must submit a signed message from the reservoir.tools oracle proving that the NFT that they are transferring has not been marked as stolen.

Swapping NFTs (buying/selling):

Users can buy and sell NFTs into the custom pool. After each trade, the virtual "x" and "y" reserves are updated depending on how many NFTs were bought or sold. On each trade, the user pays a swap fee. The fees accrue in the custom pool and can be withdrawn by the owner.

Changing NFTs:

It's possible for a user to change an NFT that they own with another NFT in the pool. When doing this, they send their NFT in and receive any NFT of their choosing from the pool. They must also pay a fixed fee which is defined by the custom pool owner. If weightings have been set, then the sum of the weights of the input NFTs must be greater than or equal to the sum of the weights of the output NFTs.


Advanced users can flashloan any NFT in the custom pool so long as they return it by the end of the call. For doing this, they have to pay a fixed fee.


The router contract is responsible for taking in a sequence of actions and executing them against the various pools. This is useful if a user wants to buy N amount of NFTs that belong to Y different pools. For example, Bob wants to buy token #1, #2, and #3. Token #1 belongs to pool A. Tokens #2, and #3 belong to pool B. Bob can submit an array of buys to the EthRouter and it will execute a buy from both pool A and pool B in one transaction.


Users can submit a sequence of buys or sells against a list of pools. They specify which NFTs they want to buy or sell and which pools to trade against. The router also handles buying and selling to shared pools. When buying or selling to shared pools, users can opt-in to whether or not they would like to pay royalties.


Users can execute a deposit into a custom pool via the router contract. This is useful so that the user does not have to approve each pool to spend their NFTs each time. Instead, they can just use the router contract which only needs to be approved once.


Users submit a sequence of change actions which are executed against a list of pools. They specify which NFTs they want to change and which NFTs they want to receive, along with the pools that they belong too.

Last updated