LpLockerv2
0xbb9fee1ceef819fe12e304f058b5e76ef8b2f17b
Verification
Verified
v0.8.35+commit.47b9dedd
Type
Contract
8,119 bytes
ABI entries
43
11 read · 13 write
License
none
Contract information
- Address
- 0xbb9fee1ceef819fe12e304f058b5e76ef8b2f17b
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.35+commit.47b9dedd
- Optimization
- Enabled
- Creator
- 0xd07EA153CC…4C10B0771e
- Creation tx
- 0x1b8103ba12…fdae3bbcb3
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (11)
MAX_CREATOR_REWARD() → uint256
TEAM_REWARD() → uint256
creatorTokenIds(address, uint256) → uint256
factory() → address
getLpTokenIdsForCreator(address) → uint256[]
owner() → address
positionManager() → address
teamOverrideRewardRecipientForToken(uint256) → address
teamRecipient() → address
tokenRewards(uint256) → uint256, uint256, tuple, tuple
version() → string
Events (10)
ClaimedRewardsCreatorRewardRecipientAdminUpdatedCreatorRewardRecipientUpdatedInterfaceRewardRecipientAdminUpdatedInterfaceRewardRecipientUpdatedOwnershipTransferredReceivedTeamOverrideRewardRecipientUpdatedTeamRecipientUpdatedTokenRewardAdded
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "owner_",
"type": "address"
},
{
"internalType": "address",
"name": "tokenFactory_",
"type": "address"
},
{
"internalType": "address",
"name": "positionManager_",
"type": "address"
},
{
"internalType": "address",
"name": "teamRecipient_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "AlreadyKnownTokenId",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "creatorReward",
"type": "uint256"
}
],
"name": "InvalidCreatorReward",
"type": "error"
},
{
"inputs": [],
"name": "InvalidMaxCreatorReward",
"type": "error"
},
{
"inputs": [],
"name": "InvalidTeamRecipient",
"type": "error"
},
{
"inputs": [],
"name": "MaxCreatorRewardNotSet",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "user",
"type": "address"
}
],
"name": "NotAllowed",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "creatorRecipient",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "interfaceRecipient",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "teamRecipient",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "token0",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "token1",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "creatorReward0",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "creatorReward1",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "interfaceReward0",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "interfaceReward1",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "teamReward0",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "teamReward1",
"type": "uint256"
}
],
"name": "ClaimedRewards",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "oldAdmin",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "CreatorRewardRecipientAdminUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "oldRecipient",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "CreatorRewardRecipientUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "oldAdmin",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "InterfaceRewardRecipientAdminUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "oldRecipient",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "InterfaceRewardRecipientUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Received",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "oldRecipient",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "TeamOverrideRewardRecipientUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "oldRecipient",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "TeamRecipientUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "creatorReward",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "creator",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "interfacer",
"type": "address"
}
],
"name": "TokenRewardAdded",
"type": "event"
},
{
"inputs": [],
"name": "MAX_CREATOR_REWARD",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TEAM_REWARD",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "creatorReward",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "admin",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"internalType": "struct ILpLockerv2.RewardRecipient",
"name": "creator",
"type": "tuple"
},
{
"components": [
{
"internalType": "address",
"name": "admin",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"internalType": "struct ILpLockerv2.RewardRecipient",
"name": "interfacer",
"type": "tuple"
}
],
"internalType": "struct ILpLockerv2.TokenRewardInfo",
"name": "tokenRewardInfo",
"type": "tuple"
}
],
"name": "addTokenReward",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "collectRewards",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "creatorTokenIds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "factory",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "user",
"type": "address"
}
],
"name": "getLpTokenIdsForCreator",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "from",
"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": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "positionManager",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "newTeamRecipient",
"type": "address"
}
],
"name": "setOverrideTeamRewardRecipientForToken",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "teamOverrideRewardRecipientForToken",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "teamRecipient",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "tokenRewards",
"outputs": [
{
"internalType": "uint256",
"name": "lpTokenId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "creatorReward",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "admin",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"internalType": "struct ILpLockerv2.RewardRecipient",
"name": "creator",
"type": "tuple"
},
{
"components": [
{
"internalType": "address",
"name": "admin",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"internalType": "struct ILpLockerv2.RewardRecipient",
"name": "interfacer",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "updateCreatorRewardAdmin",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "updateCreatorRewardRecipient",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "updateInterfaceRewardAdmin",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "updateInterfaceRewardRecipient",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newRecipient",
"type": "address"
}
],
"name": "updateTeamRecipient",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"name": "withdrawERC20",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
}
],
"name": "withdrawETH",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {IClanker} from "./interfaces/IClanker.sol";
import {ILpLockerv2} from "./interfaces/ILpLockerv2.sol";
import {INonfungiblePositionManager} from "./interfaces/uniswapv3.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
contract LpLockerv2 is Ownable, ILpLockerv2 {
string public constant version = "0.0.2";
address public positionManager;
address public factory;
uint256 public constant TEAM_REWARD = 20;
uint256 public immutable MAX_CREATOR_REWARD;
address public teamRecipient;
mapping(uint256 => TokenRewardInfo) public tokenRewards;
mapping(uint256 => address) public teamOverrideRewardRecipientForToken;
mapping(address => uint256[]) public creatorTokenIds;
constructor(
address owner_, // owner of the contract
address tokenFactory_, // Address of the clanker factory
address positionManager_, // Address of the position manager
address teamRecipient_ // address to receive team portion of the rewards
) Ownable(owner_) {
factory = tokenFactory_;
positionManager = positionManager_;
teamRecipient = teamRecipient_;
// match the factory's max creator reward
MAX_CREATOR_REWARD = IClanker(factory).MAX_CREATOR_REWARD();
if (MAX_CREATOR_REWARD == 0) {
revert MaxCreatorRewardNotSet();
}
// ensure the max creator reward and team reward add up to 100
if (MAX_CREATOR_REWARD + TEAM_REWARD != 100) {
revert InvalidMaxCreatorReward();
}
// ensure the team recipient is not the zero address
if (teamRecipient == address(0)) {
revert InvalidTeamRecipient();
}
}
modifier onlyFactory() {
if (msg.sender != factory) {
revert NotAllowed(msg.sender);
}
_;
}
// Set the override team reward recipient for a token
function setOverrideTeamRewardRecipientForToken(uint256 tokenId, address newTeamRecipient)
external
{
if (msg.sender != owner() && msg.sender != factory) {
revert NotAllowed(msg.sender);
}
address oldTeamRecipient = teamOverrideRewardRecipientForToken[tokenId];
teamOverrideRewardRecipientForToken[tokenId] = newTeamRecipient;
emit TeamOverrideRewardRecipientUpdated(tokenId, oldTeamRecipient, newTeamRecipient);
}
// Update the default team recipient
function updateTeamRecipient(address newRecipient) external onlyOwner {
address oldTeamRecipient = teamRecipient;
teamRecipient = newRecipient;
// ensure the team recipient is not the zero address
if (teamRecipient == address(0)) {
revert InvalidTeamRecipient();
}
emit TeamRecipientUpdated(oldTeamRecipient, newRecipient);
}
// Add a token reward, this is called by the factory when a token is created
function addTokenReward(TokenRewardInfo memory tokenRewardInfo) external onlyFactory {
// check that the token id is not already known
if (tokenRewards[tokenRewardInfo.lpTokenId].lpTokenId != 0) {
revert AlreadyKnownTokenId(tokenRewardInfo.lpTokenId);
}
// check that the creator reward is not greater than the max creator reward or zero
if (
tokenRewardInfo.creatorReward > MAX_CREATOR_REWARD || tokenRewardInfo.creatorReward == 0
) {
revert InvalidCreatorReward(tokenRewardInfo.creatorReward);
}
tokenRewards[tokenRewardInfo.lpTokenId] = tokenRewardInfo;
creatorTokenIds[tokenRewardInfo.creator.admin].push(tokenRewardInfo.lpTokenId);
emit TokenRewardAdded(
tokenRewardInfo.lpTokenId,
tokenRewardInfo.creatorReward,
tokenRewardInfo.creator.admin,
tokenRewardInfo.interfacer.admin
);
}
// Collect rewards for a token
function collectRewards(uint256 tokenId) public {
address teamRecipient_ = teamOverrideRewardRecipientForToken[tokenId];
if (teamRecipient_ == address(0)) {
teamRecipient_ = teamRecipient;
}
address creatorRecipient_ = tokenRewards[tokenId].creator.recipient;
if (creatorRecipient_ == address(0)) {
creatorRecipient_ = teamRecipient_;
}
address interfaceRecipient_ = tokenRewards[tokenId].interfacer.recipient;
if (interfaceRecipient_ == address(0)) {
interfaceRecipient_ = teamRecipient_;
}
// collect the rewards
INonfungiblePositionManager nonfungiblePositionManager =
INonfungiblePositionManager(positionManager);
(uint256 amount0, uint256 amount1) = nonfungiblePositionManager.collect(
INonfungiblePositionManager.CollectParams({
recipient: address(this),
amount0Max: type(uint128).max,
amount1Max: type(uint128).max,
tokenId: tokenId
})
);
(,, address token0, address token1,,,,,,,,) = nonfungiblePositionManager.positions(tokenId);
IERC20 rewardToken0 = IERC20(token0);
IERC20 rewardToken1 = IERC20(token1);
uint256 creatorReward = tokenRewards[tokenId].creatorReward;
// figure out the rewards distribution
uint256 teamReward0 = (amount0 * TEAM_REWARD) / 100;
uint256 teamReward1 = (amount1 * TEAM_REWARD) / 100;
rewardToken0.transfer(teamRecipient_, teamReward0);
rewardToken1.transfer(teamRecipient_, teamReward1);
uint256 interfaceReward0;
uint256 interfaceReward1;
uint256 creatorReward0;
uint256 creatorReward1;
if (creatorReward == MAX_CREATOR_REWARD) {
// if the creator reward is max, then there is no interface reward
creatorReward0 = amount0 - teamReward0;
creatorReward1 = amount1 - teamReward1;
rewardToken0.transfer(creatorRecipient_, creatorReward0);
rewardToken1.transfer(creatorRecipient_, creatorReward1);
} else {
// we have both a creator and interface reward
creatorReward0 = (amount0 * creatorReward) / 100;
creatorReward1 = (amount1 * creatorReward) / 100;
interfaceReward0 = amount0 - teamReward0 - creatorReward0;
interfaceReward1 = amount1 - teamReward1 - creatorReward1;
rewardToken0.transfer(interfaceRecipient_, interfaceReward0);
rewardToken1.transfer(interfaceRecipient_, interfaceReward1);
rewardToken0.transfer(creatorRecipient_, creatorReward0);
rewardToken1.transfer(creatorRecipient_, creatorReward1);
}
emit ClaimedRewards({
lpTokenId: tokenId,
creatorRecipient: creatorRecipient_,
interfaceRecipient: interfaceRecipient_,
teamRecipient: teamRecipient_,
token0: token0,
token1: token1,
teamReward0: teamReward0,
teamReward1: teamReward1,
interfaceReward0: interfaceReward0,
interfaceReward1: interfaceReward1,
creatorReward0: creatorReward0,
creatorReward1: creatorReward1
});
}
// Get the token ids for a creator (using the admin address)
function getLpTokenIdsForCreator(address user) public view returns (uint256[] memory) {
return creatorTokenIds[user];
}
// Replace the creator reward recipient
function updateCreatorRewardRecipient(uint256 tokenId, address newRecipient) external {
TokenRewardInfo memory tokenRewardInfo = tokenRewards[tokenId];
// Only admin can replace the reward recipient
if (msg.sender != tokenRewardInfo.creator.admin) {
revert NotAllowed(msg.sender);
}
// Add the new recipient
address oldRecipient = tokenRewards[tokenId].creator.recipient;
tokenRewards[tokenId].creator.recipient = newRecipient;
emit CreatorRewardRecipientUpdated(tokenId, oldRecipient, newRecipient);
}
// Replace the interface reward recipient
function updateInterfaceRewardRecipient(uint256 tokenId, address newRecipient) external {
TokenRewardInfo memory tokenRewardInfo = tokenRewards[tokenId];
// Only admin can replace the reward recipient
if (msg.sender != tokenRewardInfo.interfacer.admin) {
revert NotAllowed(msg.sender);
}
// Add the new recipient
address oldRecipient = tokenRewards[tokenId].interfacer.recipient;
tokenRewards[tokenId].interfacer.recipient = newRecipient;
emit InterfaceRewardRecipientUpdated(tokenId, oldRecipient, newRecipient);
}
// Replace the interface reward admin
function updateInterfaceRewardAdmin(uint256 tokenId, address newAdmin) external {
TokenRewardInfo memory tokenRewardInfo = tokenRewards[tokenId];
// Only admin can replace the reward admin
if (msg.sender != tokenRewardInfo.interfacer.admin) {
revert NotAllowed(msg.sender);
}
// Add the new admin
address oldAdmin = tokenRewards[tokenId].interfacer.admin;
tokenRewards[tokenId].interfacer.admin = newAdmin;
emit InterfaceRewardRecipientAdminUpdated(tokenId, oldAdmin, newAdmin);
}
// Replace the creator reward admin
function updateCreatorRewardAdmin(uint256 tokenId, address newAdmin) external {
TokenRewardInfo memory tokenRewardInfo = tokenRewards[tokenId];
// Only admin can replace the admin
if (msg.sender != tokenRewardInfo.creator.admin) {
revert NotAllowed(msg.sender);
}
// Remove the tokenId from _creatorTokenIds
uint256 length = creatorTokenIds[tokenRewardInfo.creator.admin].length;
for (uint256 i = 0; i < length; i++) {
if (creatorTokenIds[tokenRewardInfo.creator.admin][i] == tokenRewardInfo.lpTokenId) {
// Swap with the last element
creatorTokenIds[tokenRewardInfo.creator.admin][i] =
creatorTokenIds[tokenRewardInfo.creator.admin][length - 1];
// Pop the last element
creatorTokenIds[tokenRewardInfo.creator.admin].pop();
break;
}
}
// push the token id to the new admin
creatorTokenIds[newAdmin].push(tokenRewardInfo.lpTokenId);
address oldAdmin = tokenRewards[tokenId].creator.admin;
tokenRewards[tokenId].creator.admin = newAdmin;
emit CreatorRewardRecipientAdminUpdated(tokenId, oldAdmin, newAdmin);
}
// Enable contract to receive LP Tokens
function onERC721Received(address, address from, uint256 id, bytes calldata)
external
override
returns (bytes4)
{
// Only Clanker Factory can send NFTs here
if (from != factory) {
revert NotAllowed(from);
}
emit Received(from, id);
return IERC721Receiver.onERC721Received.selector;
}
// Withdraw ETH from the contract
function withdrawETH(address recipient) public onlyOwner {
payable(recipient).transfer(address(this).balance);
}
// Withdraw ERC20 tokens from the contract
function withdrawERC20(address token, address recipient) public onlyOwner {
IERC20 token_ = IERC20(token);
token_.transfer(recipient, token_.balanceOf(address(this)));
}
}
Chain explorer1041msChain node102ms