LpLocker
0x5bd90376975d7bbbd73ecef1d127955c0af4931c
Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
1,107 bytes
ABI entries
8
3 read · 2 write
License
none
Contract information
- Address
- 0x5bd90376975d7bbbd73ecef1d127955c0af4931c
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.24+commit.e11b9ed9
- Optimization
- Enabled
- Creator
- 0x937933e11a…1734Be2d5c
- Creation tx
- 0x353b8802f9…badcb1af91
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (3)
feeRecipient() → address
positionManager() → address
tokenId() → uint256
Events (2)
FeesCollectedLocked
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "_positionManager",
"type": "address"
},
{
"internalType": "address",
"name": "_feeRecipient",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "amount0",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount1",
"type": "uint256"
}
],
"name": "FeesCollected",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Locked",
"type": "event"
},
{
"inputs": [],
"name": "collectFees",
"outputs": [
{
"internalType": "uint256",
"name": "amount0",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amount1",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "feeRecipient",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "_id",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "onERC721Received",
"outputs": [
{
"internalType": "bytes4",
"name": "",
"type": "bytes4"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "positionManager",
"outputs": [
{
"internalType": "contract INonfungiblePositionManager",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "tokenId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {INonfungiblePositionManager} from "./interfaces/INonfungiblePositionManager.sol";
interface IERC721Receiver {
function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4);
}
/// @title LpLocker
/// @notice Holds a Uniswap v3 LP NFT forever.
/// Only allows fees to be collected to an immutable recipient.
/// The position can NEVER be unwound: there is no path to
/// decreaseLiquidity, transferFrom, or burn.
/// From a withdrawal standpoint this is equivalent to burning the LP,
/// while still allowing trading fees to be claimed.
contract LpLocker is IERC721Receiver {
INonfungiblePositionManager public immutable positionManager;
address public immutable feeRecipient;
uint256 public tokenId;
event Locked(uint256 indexed tokenId);
event FeesCollected(uint256 amount0, uint256 amount1);
constructor(address _positionManager, address _feeRecipient) {
require(_positionManager != address(0), "pm=0");
require(_feeRecipient != address(0), "recipient=0");
positionManager = INonfungiblePositionManager(_positionManager);
feeRecipient = _feeRecipient;
}
/// @notice Receives the LP NFT exactly once.
function onERC721Received(address, address, uint256 _id, bytes calldata)
external
returns (bytes4)
{
require(msg.sender == address(positionManager), "not v3 NFT");
require(tokenId == 0, "already locked");
tokenId = _id;
emit Locked(_id);
return IERC721Receiver.onERC721Received.selector;
}
/// @notice Anyone may call. Fees always go to the immutable recipient.
function collectFees() external returns (uint256 amount0, uint256 amount1) {
(amount0, amount1) = positionManager.collect(
INonfungiblePositionManager.CollectParams({
tokenId: tokenId,
recipient: feeRecipient,
amount0Max: type(uint128).max,
amount1Max: type(uint128).max
})
);
emit FeesCollected(amount0, amount1);
}
}
Chain explorer3072msChain node92ms