V3 Locker

Complete reference for the V3Locker contract, which handles locking of Uniswap V3 concentrated liquidity NFT positions.

Contract Address

  • Monad Testnet: 0x2D0dFc5a6731315D8f911E8534746D89B7472175

Overview

The V3 Locker enables users to lock their Uniswap V3 NFT positions (ERC-721 tokens) for a specified duration. While locked, users can:

  • Collect trading fees

  • Extend lock duration

  • Transfer ownership

  • View position details

Core Functions

lockPosition

Locks a V3 NFT position for a specified duration.

function lockPosition(
    uint256 nftId,
    uint256 unlockDate,
    address collectAddress,
    address condition
) external payable returns (uint256 lockId)

Parameters:

  • nftId: The ID of the V3 NFT position to lock

  • unlockDate: Unix timestamp when the position can be unlocked (max 10 years)

  • collectAddress: Address that will receive collected trading fees (use address(0) for msg.sender)

  • condition: Optional condition contract address (use address(0) for time-based only)

Returns:

  • lockId: Unique identifier for the created lock

Requirements:

  • Must send creationFee as msg.value

  • Must have approved the NFT to this contract

  • unlockDate must be in the future and within 10 years

  • NFT must have liquidity > 0

  • If condition is provided, it must be a valid contract

Events Emitted:

Example:


withdraw

Withdraws (unlocks) a locked position after the unlock date.

Parameters:

  • lockId: The ID of the lock to withdraw

  • receiver: Address to receive the unlocked NFT

Requirements:

  • Must be the lock owner (msg.sender == lock.owner)

  • Lock must be active

  • Current timestamp must be >= unlock date

  • If condition is set, condition must return true

  • Receiver cannot be address(0)

Events Emitted:

Example:


claimFees

Collects accumulated trading fees from the locked position.

Parameters:

  • lockId: The ID of the lock

  • amount0Max: Maximum amount of token0 to collect (use type(uint128).max for all)

  • amount1Max: Maximum amount of token1 to collect (use type(uint128).max for all)

Requirements:

  • Must be the lock owner

  • Lock must be active

Fee Distribution:

  • Protocol takes claimFeeBps (default 1%)

  • Remaining fees sent to collectAddress

Events Emitted:

Example:


Fee Collection from Uniswap V3

One of the key benefits of locking V3 positions is that you can continue collecting trading fees while your liquidity is locked. This is unique to V3 and not available in V2.

How V3 Fee Collection Works

  1. Trading Fees Accrue: As traders swap tokens in the pool, fees accumulate in your locked position

  2. You Collect Fees: Call claimFees() to collect accumulated fees to your collectAddress

  3. Protocol Fee: A small percentage (default 1%) goes to the protocol treasury

  4. You Keep the Rest: The remaining fees are sent directly to your collectAddress

Fee Collection Example

Updating Your Collect Address

You can change where fees are sent at any time:

V3 vs V2 Fee Collection

Feature
V3 Locker
V2 Locker

Fee Claiming

Yes - call claimFees()

No separate claim function

How Fees Accrue

Separate from liquidity

Increases LP token value

When You Get Fees

Anytime via claimFees()

When you unlock

Protocol Fee

1% on claimed fees

None

Important: V2 LP tokens work differently - trading fees automatically accrue to the LP token's value. You don't claim fees separately; they're reflected in the increasing value of your LP tokens. When you unlock your V2 LP tokens, you receive the full value including all accrued fees.


extendLock

Extends the unlock date of an existing lock.

Parameters:

  • lockId: The ID of the lock to extend

  • newUnlockDate: New unlock timestamp (must be later than current, max 10 years from now)

Requirements:

  • Must be the lock owner

  • Lock must be active

  • New unlock date must be > current unlock date

  • New unlock date must be <= current timestamp + 10 years

Events Emitted:

Example:


transferLockOwnership

Initiates a two-step ownership transfer (step 1 of 2).

Parameters:

  • lockId: The ID of the lock

  • newOwner: Address of the new owner

Requirements:

  • Must be the current lock owner

  • Lock must be active

  • New owner cannot be address(0)

Next Step: New owner must call acceptLockOwnership()

Example:


acceptLockOwnership

Accepts ownership transfer (step 2 of 2).

Parameters:

  • lockId: The ID of the lock

Requirements:

  • Must be the pending owner

  • Lock must be active

Events Emitted:

Example:


setCollectAddress

Updates the address that receives collected fees.

Parameters:

  • lockId: The ID of the lock

  • newCollectAddress: New address for fee collection

Requirements:

  • Must be the lock owner

  • Lock must be active

  • New address cannot be address(0)

Example:


View Functions

getOwnerLockIds

Returns all lock IDs owned by an address.

Example:


getOwnerLockCount

Returns the number of locks owned by an address.


getLock

Returns complete lock details.

Returns:

Example:


canUnlock

Checks if a lock can be unlocked now.

Example:


isLocked

Checks if an NFT is currently locked.

Example:


getPositionInfo

Returns position information from the Position Manager.


State Variables


Events


Integration Examples

Web3.js

Ethers.js


Error Reference


Gas Estimates

Approximate gas costs on Monad Testnet:

Function
Gas Cost
USD (at $3000 ETH, 0.001 gwei)

lockPosition()

~250,000

~$0.75

claimFees()

~150,000

~$0.45

withdraw()

~180,000

~$0.54

extendLock()

~50,000

~$0.15

transferLockOwnership()

~45,000

~$0.14

Note: Actual costs may vary based on network congestion and position complexity


Last updated