IntegrationsQuick StartBurn And Delegate Fees
Functions
The DelegatedPositionVault allows liquidity providers to permanently lock their Hyperswap V2/V3 positions and delegate fee collection rights via NFTs. This guide explains how to integrate with the…
Overview
The DelegatedPositionVault allows liquidity providers to permanently lock their Hyperswap V2/V3 positions and delegate fee collection rights via NFTs. This guide explains how to integrate with the vault contract.
Contract Address
HyperEVM: 0x744C89B7b7F8Cb1E955B1Dcd842A5378d75c96Dc
Key Concepts
- Permanent Lock: Once positions are delegated, the underlying liquidity is locked forever
- Fee Collection NFTs: Users receive ERC721 NFTs that grant the right to claim accumulated fees
- No Principal Withdrawal: Only fees can be claimed - the original liquidity remains permanently staked
Integration Steps
1. Approve the Vault
Before delegating positions, users must approve the vault to transfer their assets:
For V3 Positions:
// Approve the vault to transfer your V3 NFT
INonfungiblePositionManager(NFPM).approve(VAULT_ADDRESS, tokenId);For V2 Positions:
// Approve the vault to transfer your LP tokens
IERC20(pairAddress).approve(VAULT_ADDRESS, amount);2. Delegate Positions
Delegating V3 Positions:
// Burn V3 position and mint fee collection NFT
uint256 delegatedTokenId = vault.burnV3(
tokenId, // V3 position NFT token ID
feeCollector // Address to receive the fee collection NFT
);Delegating V2 Positions:
// Burn V2 LP tokens and mint fee collection NFT
uint256 delegatedTokenId = vault.burnV2(
pair, // IHyperswapV2Pair contract
amount, // Amount of LP tokens to delegate
feeCollector // Address to receive the fee collection NFT
);3. Claim Fees
Only the owner of the delegated position NFT can claim fees:
// Claim fees from a single position
vault.claim(delegatedTokenId);
// Claim fees from multiple positions at once
uint256[] memory tokenIds = [tokenId1, tokenId2, tokenId3];
vault.bulkClaim(tokenIds);Integration Examples
Example 1: Simple Fee Delegation
contract SimpleDelegation {
address public constant VAULT = 0xfB04F2679962484ef7bCeC75598E169888a67fBb;
// Delegate V3 position to yourself
function delegateV3Position(uint256 v3TokenId) external {
// Approve vault
INonfungiblePositionManager(NFPM).approve(VAULT, v3TokenId);
// Delegate position, receiving NFT to same address
uint256 delegatedId = IDelegatedPositionVault(VAULT).burnV3(
v3TokenId,
msg.sender
);
emit V3PositionDelegated(v3TokenId, delegatedId);
}
// Delegate V2 LP tokens to yourself
function delegateV2Position(address pairAddress, uint256 lpAmount) external {
// Approve vault to transfer LP tokens
IERC20(pairAddress).approve(VAULT, lpAmount);
// Delegate LP tokens, receiving NFT to same address
uint256 delegatedId = IDelegatedPositionVault(VAULT).burnV2(
pairAddress,
lpAmount,
msg.sender
);
emit V2PositionDelegated(pairAddress, lpAmount, delegatedId);
}
// Claim fees from your delegated position
function claimMyFees(uint256 delegatedId) external {
// Only the NFT owner can claim
IDelegatedPositionVault(VAULT).claim(delegatedId);
}
}Events to Monitor
// Emitted when a position is delegated
event Burn(
uint256 indexed tokenId,
uint256 indexed positionIdOrAmountLpTokens,
PositionType positionType
);
// Emitted when fees are claimed
event Claim(
uint256 indexed tokenId,
uint256 indexed positionIdOrAmountLpTokens,
PositionType positionType,
uint256 amount0,
uint256 amount1
);Important Considerations
- Irreversible Action: Delegating positions is permanent - ensure users understand this
- Fee Accumulation: Fees continue to accumulate even if not claimed regularly
- NFT Ownership: Only the NFT holder can claim fees - losing the NFT means losing fee rights
- Gas Optimization: Use
bulkClaimfor multiple positions to save gas - Emergency Pause: The contract can be paused by the owner in emergencies
Complete Contract Interface
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
interface IDelegatedPositionVault {
// Enums
enum PositionType { V3, V2 }
// Events
event Burn(
uint256 indexed tokenId,
uint256 indexed positionIdOrAmountLpTokens,
PositionType positionType
);
event Claim(
uint256 indexed tokenId,
uint256 indexed positionIdOrAmountLpTokens,
PositionType positionType,
uint256 amount0,
uint256 amount1
);
// Core Functions
function burnV3(uint256 tokenId, address feeCollector)
external returns (uint256 positionId);
function burnV2(address pair, uint256 amount, address feeCollector)
external returns (uint256 positionId);
function claim(uint256 tokenId) external;
function bulkClaim(uint256[] calldata tokenIds) external;
// Admin Functions
function pause() external;
function unpause() external;
// View Functions
function delegatedPositions(uint256 tokenId) external view returns (
PositionType positionType,
uint256 tokenIdOrAmountLpTokens,
address pair,
address token0,
address token1,
uint24 fee,
uint256 sqrtK,
bool exists
);
function tokenIdCounter() external view returns (uint256);
function paused() external view returns (bool);
function owner() external view returns (address);
// ERC721 Functions
function ownerOf(uint256 tokenId) external view returns (address);
function balanceOf(address owner) external view returns (uint256);
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function transferFrom(address from, address to, uint256 tokenId) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}Security Best Practices
- Always verify the vault contract address
- Ensure proper approval amounts (use exact amounts, not max)
- Implement access controls if building a fee collection system
- Monitor the
paused()state before operations - Handle reverts gracefully in your integration