# Locking v3 Positions

There is **NO WARRANTY** provided with this code reference. The concept here is to transfer a Koi Finance v3 position NFT into this contract which permanently locks liquidity, yet allows the deployed owner to collect trading fees on this position in perpetuity until the owner is relinquished. \
\
When calling collect, the recipient param should be the account that is receiving the fees.

```solidity
pragma solidity =0.7.6;
pragma abicoder v2;

/// @title V3 Locker & Fee Claimer
contract V3PositionLocker {
    address public owner;
    address public immutable nonfungiblePositionManager;

    constructor(address _nonfungiblePositionManager) {
        owner = msg.sender;
        nonfungiblePositionManager = _nonfungiblePositionManager;
    }

    function setOwner(address _owner) external {
        require(msg.sender == owner);
        owner = _owner;
    }

    function collect(INonfungiblePositionManager.CollectParams calldata params) external {
        require(msg.sender == owner, "Not owner");

        (uint256 amount0, uint256 amount1) = INonfungiblePositionManager(nonfungiblePositionManager).collect(params);
    }

    function saveToken(address _token, address _destination, uint _amount) external {
        require(msg.sender == owner, "Not owner");
        IERC20(_token).transfer(_destination, _amount);
    }
}

interface INonfungiblePositionManager {
    struct CollectParams {
        uint256 tokenId;
        address recipient;
        uint128 amount0Max;
        uint128 amount1Max;
    }

    /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient
    /// @param params tokenId The ID of the NFT for which tokens are being collected,
    /// recipient The account that should receive the tokens,
    /// amount0Max The maximum amount of token0 to collect,
    /// amount1Max The maximum amount of token1 to collect
    /// @return amount0 The amount of fees collected in token0
    /// @return amount1 The amount of fees collected in token1
    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);
}

interface IERC20 {
    function transfer(address recipient, uint256 amount) external returns (bool);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.koi.finance/accessory/locking-v3-positions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
