Uniswap v3 NFT Management
Overview Each Uniswap v3 farming setup is linked to a single Uniswap v3 NFT that represents a single price curve for a liquidity pool. The curve's parameters are established by the host during the creation of the setup (see here) within its parent contract.
This means that the farming contract itself is the holder of each of its setups' NFT, and that all users who create a farming position by adding or removing liquidity to a given setup interact with the same NFT. Advantages
Having a single NFT per setup—rather than one per farmer—has several advantages. For example:
farming contracts & their setups can be tailored with the right curves for projects & tokens
it enables a variety of ways to incentivize farmers, such as giving higher rewards to wider curves that better secure liquidity, or giving lower rewards to smaller curves that are riskier for liquidity but which earn farmers more trading fees
farming is much cheaper, as farmers don't have to mint a new NFT every time they open a position; instead, they all just add liquidity to or remove liquidity from the same NFT
by eschewing excessively granular liquidity on Uniswap v3—i.e. liquidity with many different curves, and thus many NFTs—trading is cheaper too, as each swap in a v3 pool activates all NFTs at a cost
NFT Minting & Burning
The following NFT parameters are established when a setup is created:
LP
address
-> from which the two tokenaddresses
and the fee of the pool are retrievedtickLower
->parameter representing the value oftickLower
used to create the Uniswap v3 NFT for the setup.tickUpper
->parameter representing the value oftickUpper
used to create the Uniswap v3 NFT for the setup.
These are saved within the FarmingSetupInfo
. Once the setup is active—i.e when the first user creates a new position within that setup—the NFT is minted by taking them as the mintParams
to create the NFT position via the Uniswap v3 INonfungiblePositionManager:
When the setup comes to an end (e.g. at the end block) and is deactivated (e.g. when the last position is withdrawn, leaving the setup with zero liquidity), it is deleted from the contract's memory (just as with Generation 1 contracts) and the NFT is burned via the INonfungiblePositionManager burn method.
If a setup has been customized to renew after it ends (through the _toggleSetup
function), a new NFT will be minted when it is (i.e when the first position is opened in it) with the same parameters as before. This ensures that a setup always corresponds to the same equivalent NFT.
Trading Fee Management
Trading fees in Uniswap v3 are managed differently than in other AMMs supported by the Covenant AMM Aggregator (such as Uniswap v2) as they can be withdrawn separately from liquidity. Accordingly, Covenant Farming contracts for Uniswap v3 are designed with an intra-NFT fee-splitting logic, so that Farmers of the same setup (and thus the same NFT) can withdraw the fees they have earned individually.
The calculation of the reward for a single farmer's position contains information about the time (blocks) the farmer has spent in the farming setup and the amount of liquidity he has pooled. This calculation is used to determine how much he will receive in trading fees at the exact moment he claims his reward in accordance with the formula of the fee-splitting logic, which is:
The amount of fees for an individual farmer is therefore given by:
FM -> Fee Multiplier
FP -> Fee per Position i -> Individual farmer
positionreward = amount of reward tokens being withdrawn by the user
totalrewardtokens = reward per Block * numbers of blocks from the start block until the current block
totalrewardredeemed = total reward tokens withdrawn by all users of the setup up to the current block
So, when a user withdraws his or her reward, his or her share of the trading fees is also withdrawn. Trading fees cannot be withdrawn separately from the reward.
Linking the fee-splitting logic to the reward instead of directly to the liquidity prevents a user who adds a large amount of liquidity to the setup for a few blocks from withdrawing more fees than they've earned.
N.B. Using the sharing NFT architecture users can experience impermanent losses in the fees they have earned if the trading volume in a pool drops too much.
Liquidity
The architecture of Covenant Farming v1.0 contracts was relatively easy to adapt to Uniswap v3. Although Uniswap v3 doesn't use fungible LP tokens, the v3 NFTs do use the "liquidity
" parameter which represents the liquidity within an NFT's curve. Thisliquidity
parameter is used in v1.5 contracts (instead of LP tokens, like in v1.0 contracts) for farming features such as position reward calculation.
So, for example, in OpenPosition
operations, the liquidity
parameter is used as follows:
The liquidityAmount
parameter represents the liquidity amount in a Uniswap v3 farming setup.
The same thing applies to the addLiquidity
operation:
For WithdrawLiquidity
operations, the liquidity
parameter is used as follows:
What was managed through the LP token amount in v1.0 contracts is now managed through the liquidity
parameter of the NFT in v1.5 contracts.
Last updated