Nexera-FiAdapters & DeFi ProtocolsUniswap

Uniswap v3 Protocol

Overview

Uniswap is a decentralized exchange (DEX) protocol that allows users to provide and trade liquidity in a range of assets on EVM blockchains. Uniswap v3 is the 3rd iteration of the protocol which introduces the non-fungible liquidity positions and concentrated liquidity concepts, where liquidity providers (LPs) are able to specify a price range for their liquidity, thereby maximizing capital efficiency.

The Nexera-Fi UniswapAdapter interacts with and utilizes the following three key components of Uniswap v3:

In the following sections, we'll provide an overview of these contracts and their methods that Nexera-Fi UniswapAdapter interacts with.

Interactions with UniswapAdapter

The UniswapAdapter interacts with the Uniswap v3 protocol by calling the methods presented in the diagram below. Each method serves a specific purpose within the adapter, enabling strategies to seamlessly integrate deposits, withdrawals, and swaps of assets on the Uniswap v3 platform.

graph LR; style Nexera_Fi fill:#9999dd; style Uniswap_v3 fill:#ff66b2; subgraph Nexera_Fi A[<b> UniswapAdapter </b>] end subgraph Uniswap_v3 B["<b>NonFungiblePositionManager"] C["<b>SwapRouter"] end A --> |<b>positions</b>: <i>Retrieve position info</i>| B A --> |<b>collect</b>: <i>Collect earned fees</i>| B A --> |<b>mint</b>: <i>Create new liquidity position</i>| B A --> |<b>increaseLiquidity</b>: <i>Add liquidity</i>| B A --> |<b>decreaseLiquidity</b>: <i>Reduce liquidity</i>| B A --> |<b>refundETH</b>: <i>Refund excess ETH</i>| B A --> |<b>safeApprove</b>: <i>Allowances for token transfers</i>| B & C A --> |<b>exactInputSingle</b>: <i>Token swaps</i>| C

NonfungiblePositionManager

The NonfungiblePositionManager contract is a core component of the Uniswap v3 protocol. It allows users to manage liquidity positions, create new positions, and modify existing ones.

In the context of the Nexera-Fi UniswapAdapter, these six methods come into play:

  1. positions: Retrieves information about a specific liquidity position.
  2. collect: Collects fees earned from a liquidity position.
  3. mint: Creates a new liquidity position by depositing assets into a specific pool.
  4. increaseLiquidity: Adds additional liquidity to an existing position.
  5. decreaseLiquidity: Reduces the liquidity of an existing position.
  6. refundETH: Refunds excess ETH (if any) from a position after decreasing liquidity and swap actions.

Methods

positions

Retrieves information about a specific liquidity position associated with a give NFT LP token.

function positions(uint256 tokenId)
    external
    view
    returns (
        uint96 nonce,
        address operator,
        address token0,
        address token1,
        uint24 fee,
        int24 tickLower,
        int24 tickUpper,
        uint128 liquidity,
        uint256 feeGrowthInside0LastX128,
        uint256 feeGrowthInside1LastX128,
        uint128 tokensOwed0,
        uint128 tokensOwed1
    );

This method is invoked by the following UniswapAdapter functions:

When this function is executed with a non-zero tokenId provided in the DepositExtraData, the Adapter adds liquidity to an existing position. To achieve this, the Adapter first obtains the addresses of the two tokens (token0 & token1) in the associated Pool by invoking the positions method. These acquired addresses are cross-checked for inconsistencies with the respective provided data within DepositExtraData. Consequently, if any of the acquired addresses is zero address, they are replaced with the address of the wrapped native token stored in storage during initialization. These addresses are then utilized to construct the necessary data for increasing liquidity within the target position.

This helper function invokes the positions method to retrieve the addresses of the two tokens (token0 & token1) associated with a particular liquidity position, identified by the provided NFT LP tokenId. This step is essential to verify and confirm the consistency between the tokens specified in the input data (expectedIn) and the actual tokens held within the liquidity position. Thus, the Adapter ensures that it operates with precise information about the assets contained in the liquidity position, thereby safeguarding the integrity of the transactions.

This function invokes the positions method to retrieve key data related to a specific liquidity position identified by the tokenId within withdrawExtraData. This data includes the liquidity, as well as the amounts of tokens owed (tokensOwed0 and tokensOwed1) for the target position before and after the liquidity is decreased. These steps are crucial for verifying the consistency between the actual input tokens (the assets received by the Adapter) and the expected input tokens defined in expectedIn.


collect

Collects up to a maximum amount of fees owed to a specific position to the recipient

 function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);

This method is invoked by the following UniswapAdapter function:

The collect method is invoked to perform the operation of claiming earned fees from a specific liquidity position identified by the tokenId within the extraData input parameter. In the context of the function the captured collected amounts (amount0 & amount1) are cross-validated against the expected values specified in expectedIn input parameter, thereby safeguarding the integrity of the transaction.


mint

Creates a new position wrapped in a NFT LP token.

function mint(MintParams calldata params)
    external
    payable
    returns (
        uint256 tokenId,
        uint128 liquidity,
        uint256 amount0,
        uint256 amount1
    );

This method is invoked by the following UniswapAdapter function:

When this function is executed with tokenId==0 provided in the DepositExtraData, the Adapter creates a new NFT liquidity position by invoking the mint method with the necessary params input argument. In the context of the function the captured amounts (amount0 & amount1) are cross-validated against the expected amounts defined in expectedIn to verify they meet or exceed the specified minimums for integrity.


increaseLiquidity

Increases the amount of liquidity in a position.

function increaseLiquidity(IncreaseLiquidityParams calldata params)
    external
    payable
    returns (
        uint128 liquidity,
        uint256 amount0,
        uint256 amount1
    );

This method is invoked by the following UniswapAdapter function:

In the context of this function, when the DepositExtraData.tokenId is non-zero, the Adapter is directed to add liquidity to an existing NFT LP position. To accomplish this, the Adapter must interact with the increaseLiquidity method provided by the NonfungiblePositionManager. This method allows the Adapter to increase the liquidity within the specified NFT position by supplying the desired amounts of token0 and token1.


decreaseLiquidity

Decreases the amount of liquidity in a position and accounts it to the position.

function decreaseLiquidity(DecreaseLiquidityParams calldata params)
    external
    payable
    returns (uint256 amount0, uint256 amount1);

This method is invoked by the following UniswapAdapter function:

In the context of this function the Adapter is directed to remove liquidity from an existing NFT LP position. To accomplish this, the Adapter must interact with the decreaseLiquidity method provided by the NonfungiblePositionManager. This method allows the Adapter to decrease the liquidity within the specified NFT position by supplying the desired amounts of token0 and token1 defined in withdrawExtraData and expectedIn input parameters, ensuring that it aligns with the provided percentage to withdraw.


refundETH

Refunds excess ETH (if any) held by the NonfungiblePositionManager contract after decreasing liquidity and swap actions.

function refundETH() external payable;

This method is invoked by the following UniswapAdapter functions:

In both the _swap and _deposit functions of the Adapter, the refundETH method provided by the NonfungiblePositionManager is invoked to ensure that any excess ETH sent during the transaction is returned to the Adapter. This is a safety measure to prevent the loss of native currency in case it's not fully utilized during the operation.

SwapRouter

The SwapRouter contract enables the swapping of tokens within the Uniswap v3 protocol.

Methods

exactInputSingle

Performs a single token swap with a specific input amount.

function exactInputSingle(ExactInputSingleParams calldata params)
    external
    payable
    checkDeadline(params.deadline)
    returns (uint256 amountOut);

This method is invoked by the following UniswapAdapter function:

In the context of this function, the Adapter invokes the exactInputSingle method of the SwapRouter with parameters constructed from the extraData, out, and expectedIn input arguments. These parameters encompass the desired fee tier, the desired sqrtPriceLimitX96 for the swap, the target tokens (tokenIn & tokenOut) as well as the desired and minium amounts. If any of the target token addresses provided are set to the zero address, they are replaced with the address of the wrapped native token stored in storage during initialization. Moreover, the returned amount0 from the method is captured and internally cross-validated to ensure that it meets or exceeds the expected amount specified in the expectedIn input argument.

TransferHelper

The TransferHelper library includes functions for safely transferring tokens and handling token approvals.

Methods

safeApprove

Safely approves a contract to spend a specified amount of tokens.

function safeApprove(address token, address to, uint256 value) internal;

This method is invoked by the following UniswapAdapter functions:

In this function, the Adapter employs a multi-step approach to ensure secure token transfers during the deposit process. First, it checks the current allowances of the NonFungiblePositionManager for the target tokens (token0 & token1). If allowances are already set, it resets them to zero using the safeApprove method. Subsequently, it sets new allowances with the exact amounts defined in the out input argument. This process actively manages token spending permissions for the involved tokens, enhancing the security of the deposit operation.

In this function, the Adapter enables secure token swaps by setting the allowance for the SwapRouter contract. The allowance is established using the safeApprove method, where the exact spending permissions granted to the SwapRouter are provided.


Please note: For detailed information about Uniswap v3 protocol, consult the official Uniswap v3 documentation.

On this page