StoxesFunV3Locker

0x134d32ea27ba2abb28cf210b5dc814f33ea570b5

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
6,176 bytes
ABI entries
48
21 read · 6 write
License
none

Contract information

Address
0x134d32ea27ba2abb28cf210b5dc814f33ea570b5
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0x9c89369d79…f8a6a16e04

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (21)

BUYBACK_FEE_BPS()uint256
CREATOR_FEE_BPS()uint256
DEAD()address
POOL_FEE()uint24
WETH()address
allLockedTokens(uint256)address
allLockedTokensLength()uint256
buybackExecutor()address
creatorWalletOf(address)address
factory()address
locks(address)uint256, address, address, bool
onERC721Received(address, address, uint256, bytes)bytes4
owner()address
pendingBuybackWeth(address)uint256
positionIdOf(address)uint256
positionManager()address
stats(address)uint256, uint256, uint256, uint256, uint64
statsOf(address)uint256, uint256, uint256, uint256, uint256, uint64
swapRouter()address
treasury()address
usedTokenId(uint256)bool

Events (8)

BuybackAccruedBuybackBurnedBuybackDeferredBuybackExecutorChangedFactoryChangedFeesCollectedOwnershipTransferredPositionLocked

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "positionManager_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "swapRouter_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "weth_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "treasury_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "admin_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "AlreadyLocked",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidParams",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotBuybackExecutor",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotFactory",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotOwner",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotPositionManager",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NothingToBuyback",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "PositionNotOwned",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "Reentrancy",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "TransferFailed",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "UnknownToken",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ZeroAddress",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wethAdded",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wethPending",
        "type": "uint256"
      }
    ],
    "name": "BuybackAccrued",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wethIn",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensBurned",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensBurnedDirect",
        "type": "uint256"
      }
    ],
    "name": "BuybackBurned",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wethPending",
        "type": "uint256"
      }
    ],
    "name": "BuybackDeferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "oldExecutor",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newExecutor",
        "type": "address"
      }
    ],
    "name": "BuybackExecutorChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "oldFactory",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newFactory",
        "type": "address"
      }
    ],
    "name": "FactoryChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "caller",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wethToCreator",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "wethToTreasury",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokenToCreator",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokenToTreasury",
        "type": "uint256"
      }
    ],
    "name": "FeesCollected",
    "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": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "creatorWallet",
        "type": "address"
      }
    ],
    "name": "PositionLocked",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "BUYBACK_FEE_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "CREATOR_FEE_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "DEAD",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "POOL_FEE",
    "outputs": [
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "WETH",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "allLockedTokens",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "allLockedTokensLength",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "buybackExecutor",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "collect",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "wethAmount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "tokenAmount",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "creatorWalletOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "factory",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "locks",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "creatorWallet",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "tokenIsToken0",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      },
      {
        "internalType": "bytes",
        "name": "",
        "type": "bytes"
      }
    ],
    "name": "onERC721Received",
    "outputs": [
      {
        "internalType": "bytes4",
        "name": "",
        "type": "bytes4"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "pendingBuybackWeth",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "positionIdOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "positionManager",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "creatorWallet",
        "type": "address"
      }
    ],
    "name": "register",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "minTokensOut",
        "type": "uint256"
      }
    ],
    "name": "runBuyback",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "tokensBought",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newExecutor",
        "type": "address"
      }
    ],
    "name": "setBuybackExecutor",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newFactory",
        "type": "address"
      }
    ],
    "name": "setFactory",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "stats",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "creatorWethPaid",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "creatorTokenPaid",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "buybackWethSpent",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "tokensBurned",
        "type": "uint256"
      },
      {
        "internalType": "uint64",
        "name": "lastCollectAt",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "statsOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "creatorWethPaid",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "creatorTokenPaid",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "buybackWethSpent",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "tokensBurned",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "pendingBuyback",
        "type": "uint256"
      },
      {
        "internalType": "uint64",
        "name": "lastCollectAt",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapRouter",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "treasury",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "usedTokenId",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import {OwnableLite, ReentrancyGuardLite, SafeERC20Lite} from "./base/Common.sol";
import {INonfungiblePositionManager, ISwapRouter02} from "./interfaces/IUniswapV3.sol";

interface IERC20ApproveLite {
    function approve(address spender, uint256 amount) external returns (bool);
}

/// @title  StoxesFunV3Locker — permanent lock for stoxes.fun V3 launch liquidity
/// @author stoxes.fun
/// @notice Owns every non-taxed launch's Uniswap V3 position NFT FOREVER.
///         There is deliberately NO function that can transfer an NFT out or
///         decrease liquidity — once a position lands here, the liquidity is
///         locked for the life of the chain (bow.fun model). The only value
///         path is `collect()`: anyone may trigger a fee collection.
///
///         v3 fee split (both collected currencies):
///           - 17.5% -> the launch creator's immutable fee wallet
///           - 17.5% -> BUYBACK & BURN of the launch token:
///               * the WETH share accrues in `pendingBuybackWeth[token]`; the
///                 swap itself is executed SEPARATELY via `runBuyback`, which
///                 is executor-gated and takes a caller-supplied `minTokensOut`
///                 slippage floor (a permissionless swap with no floor would be
///                 sandwichable — the decoupling is the audit fix)
///               * the token-side share is burned directly to 0xdead
///           - 65.0% -> the platform treasury (remainder)
///
///         If the buyback swap fails (e.g. pool state edge), the WETH stays
///         parked in `pendingBuybackWeth[token]` and is retried on the next
///         `runBuyback` — a swap failure can never brick fee collection, and
///         no value is ever stranded.
///
///         Per-token cumulative counters (`stats`) expose creator fees paid,
///         WETH spent on buybacks, tokens burned, and the last collect time —
///         everything a UI needs to show the split publicly, on-chain.
///
///         The owner (platform admin) can only rotate the factory pointer for
///         FUTURE registrations (mirrors the Earnings splitter's setFactory) —
///         it has no path to locked NFTs, recorded creator wallets, or fees.
contract StoxesFunV3Locker is OwnableLite, ReentrancyGuardLite {
    using SafeERC20Lite for address;

    /// @notice Creator share of collected pool fees, in bps.
    uint256 public constant CREATOR_FEE_BPS = 1750;

    /// @notice Buyback-and-burn share of collected pool fees, in bps.
    uint256 public constant BUYBACK_FEE_BPS = 1750;

    /// @notice The 1% fee tier every stoxes.fun V3 launch pool uses.
    uint24 public constant POOL_FEE = 10_000;

    /// @notice Canonical burn address.
    address public constant DEAD = 0x000000000000000000000000000000000000dEaD;

    /// @notice The Uniswap V3 NonfungiblePositionManager on Robinhood Chain.
    address public immutable positionManager;

    /// @notice The canonical SwapRouter02 used for buyback swaps.
    address public immutable swapRouter;

    /// @notice WETH on Robinhood Chain.
    address public immutable WETH;

    /// @notice Platform treasury receiving the 65% fee share. Immutable.
    address public immutable treasury;

    /// @notice The stoxes.fun V3 launch factory allowed to register locks.
    address public factory;

    /// @notice The wallet allowed to execute buyback swaps (the keeper). The
    ///         owner may rotate it; it has NO other powers — the swap output
    ///         always goes to 0xdead and the input is the parked buyback WETH.
    address public buybackExecutor;

    /// @notice Position NFT ids already registered (a tokenId can never back
    ///         two lock records).
    mapping(uint256 => bool) public usedTokenId;

    struct Lock {
        uint256 tokenId;
        address token;
        /// @dev Immutable after registration — creator fee payouts always land here.
        address creatorWallet;
        /// @dev True when the launch token is token0 in the pool (token < WETH).
        bool tokenIsToken0;
    }

    /// @notice Public, cumulative per-token fee-split accounting.
    struct TokenStats {
        uint256 creatorWethPaid; // lifetime WETH paid to the creator wallet
        uint256 creatorTokenPaid; // lifetime launch tokens paid to the creator wallet
        uint256 buybackWethSpent; // lifetime WETH swapped into buyback burns
        uint256 tokensBurned; // lifetime launch tokens sent to 0xdead by collect
        uint64 lastCollectAt; // timestamp of the last collect() for this token
    }

    /// @notice token address => its permanent lock record.
    mapping(address => Lock) public locks;

    /// @notice token address => cumulative fee-split stats.
    mapping(address => TokenStats) public stats;

    /// @notice Buyback WETH parked after a failed swap, retried next collect.
    mapping(address => uint256) public pendingBuybackWeth;

    /// @notice All locked launch tokens, in registration order.
    address[] public allLockedTokens;

    event FactoryChanged(address indexed oldFactory, address indexed newFactory);
    event PositionLocked(
        address indexed token, uint256 indexed tokenId, address indexed creatorWallet
    );
    event FeesCollected(
        address indexed token,
        address indexed caller,
        uint256 wethToCreator,
        uint256 wethToTreasury,
        uint256 tokenToCreator,
        uint256 tokenToTreasury
    );
    event BuybackBurned(
        address indexed token, uint256 wethIn, uint256 tokensBurned, uint256 tokensBurnedDirect
    );
    event BuybackDeferred(address indexed token, uint256 wethPending);
    event BuybackAccrued(address indexed token, uint256 wethAdded, uint256 wethPending);
    event BuybackExecutorChanged(address indexed oldExecutor, address indexed newExecutor);

    error NotFactory();
    error NotPositionManager();
    error NotBuybackExecutor();
    error InvalidParams();
    error AlreadyLocked();
    error UnknownToken();
    error PositionNotOwned();
    error NothingToBuyback();

    constructor(
        address positionManager_,
        address swapRouter_,
        address weth_,
        address treasury_,
        address admin_
    ) {
        if (
            positionManager_ == address(0) || swapRouter_ == address(0) || weth_ == address(0)
                || treasury_ == address(0)
        ) {
            revert InvalidParams();
        }
        positionManager = positionManager_;
        swapRouter = swapRouter_;
        WETH = weth_;
        treasury = treasury_;
        buybackExecutor = admin_;
        _initOwner(admin_);
    }

    /// @notice Rotates the buyback executor (the keeper wallet driving
    ///         `runBuyback`). Executor powers stop at triggering the swap —
    ///         output is always burned, input is always the parked WETH.
    function setBuybackExecutor(address newExecutor) external onlyOwner {
        if (newExecutor == address(0)) revert InvalidParams();
        emit BuybackExecutorChanged(buybackExecutor, newExecutor);
        buybackExecutor = newExecutor;
    }

    /// @notice Points the locker at the launch factory (or a rotated one).
    ///         Affects FUTURE registrations only; existing locks are untouched.
    function setFactory(address newFactory) external onlyOwner {
        if (newFactory == address(0)) revert InvalidParams();
        emit FactoryChanged(factory, newFactory);
        factory = newFactory;
    }

    /// @notice Records a freshly-minted launch position. Called by the factory
    ///         in the same transaction that mints the NFT to this locker.
    /// @dev    Hardened: the NFT must ALREADY be owned by this locker (a record
    ///         can never point at liquidity that is not actually locked here),
    ///         and a tokenId can never back two records.
    function register(address token, uint256 tokenId, address creatorWallet) external {
        if (msg.sender != factory) revert NotFactory();
        if (token == address(0) || creatorWallet == address(0)) revert InvalidParams();
        if (locks[token].creatorWallet != address(0)) revert AlreadyLocked();
        if (usedTokenId[tokenId]) revert AlreadyLocked();
        if (INonfungiblePositionManager(positionManager).ownerOf(tokenId) != address(this)) {
            revert PositionNotOwned();
        }
        usedTokenId[tokenId] = true;
        locks[token] = Lock({
            tokenId: tokenId,
            token: token,
            creatorWallet: creatorWallet,
            tokenIsToken0: token < WETH
        });
        allLockedTokens.push(token);
        emit PositionLocked(token, tokenId, creatorWallet);
    }

    /// @notice PERMISSIONLESS fee collection: pulls all accrued pool fees for
    ///         `token`'s locked position and splits both currencies
    ///         17.5% creator / 17.5% buyback&burn / 65% treasury. Anyone can
    ///         call ("COLLECT + BURN"); the caller never receives funds.
    function collect(address token)
        external
        nonReentrant
        returns (uint256 wethAmount, uint256 tokenAmount)
    {
        Lock memory lock = locks[token];
        if (lock.creatorWallet == address(0)) revert UnknownToken();

        (uint256 amount0, uint256 amount1) = INonfungiblePositionManager(positionManager).collect(
            INonfungiblePositionManager.CollectParams({
                tokenId: lock.tokenId,
                recipient: address(this),
                amount0Max: type(uint128).max,
                amount1Max: type(uint128).max
            })
        );

        (tokenAmount, wethAmount) =
            lock.tokenIsToken0 ? (amount0, amount1) : (amount1, amount0);

        uint256 wethToCreator = (wethAmount * CREATOR_FEE_BPS) / 10_000;
        uint256 wethToBuyback = (wethAmount * BUYBACK_FEE_BPS) / 10_000;
        uint256 wethToTreasury = wethAmount - wethToCreator - wethToBuyback;
        uint256 tokenToCreator = (tokenAmount * CREATOR_FEE_BPS) / 10_000;
        uint256 tokenToBurn = (tokenAmount * BUYBACK_FEE_BPS) / 10_000;
        uint256 tokenToTreasury = tokenAmount - tokenToCreator - tokenToBurn;

        if (wethToCreator > 0) WETH.safeTransfer(lock.creatorWallet, wethToCreator);
        if (wethToTreasury > 0) WETH.safeTransfer(treasury, wethToTreasury);
        if (tokenToCreator > 0) token.safeTransfer(lock.creatorWallet, tokenToCreator);
        if (tokenToTreasury > 0) token.safeTransfer(treasury, tokenToTreasury);

        // Direct burn of the token-side buyback share.
        if (tokenToBurn > 0) token.safeTransfer(DEAD, tokenToBurn);

        // Park the WETH buyback share; the swap runs separately via
        // `runBuyback` with an executor-supplied slippage floor (collect is
        // permissionless, so an in-line floorless swap would be sandwichable).
        if (wethToBuyback > 0) {
            uint256 newPending = pendingBuybackWeth[token] + wethToBuyback;
            pendingBuybackWeth[token] = newPending;
            emit BuybackAccrued(token, wethToBuyback, newPending);
        }

        TokenStats storage s = stats[token];
        s.creatorWethPaid += wethToCreator;
        s.creatorTokenPaid += tokenToCreator;
        s.tokensBurned += tokenToBurn;
        s.lastCollectAt = uint64(block.timestamp);
        if (tokenToBurn > 0) emit BuybackBurned(token, 0, 0, tokenToBurn);

        emit FeesCollected(
            token, msg.sender, wethToCreator, wethToTreasury, tokenToCreator, tokenToTreasury
        );
    }

    /// @notice Executes the parked buyback for `token`: swaps the accrued WETH
    ///         through the token's own pool straight to 0xdead, enforcing the
    ///         executor-supplied `minTokensOut` slippage floor (quoted off-chain
    ///         just before the call). Executor-gated because the floor is
    ///         caller-supplied; a failing swap re-parks the WETH.
    function runBuyback(address token, uint256 minTokensOut)
        external
        nonReentrant
        returns (uint256 tokensBought)
    {
        if (msg.sender != buybackExecutor) revert NotBuybackExecutor();
        if (minTokensOut == 0) revert InvalidParams();
        if (locks[token].creatorWallet == address(0)) revert UnknownToken();
        uint256 buybackIn = pendingBuybackWeth[token];
        if (buybackIn == 0) revert NothingToBuyback();

        pendingBuybackWeth[token] = 0;
        IERC20ApproveLite(WETH).approve(swapRouter, buybackIn);
        try ISwapRouter02(swapRouter).exactInputSingle(
            ISwapRouter02.ExactInputSingleParams({
                tokenIn: WETH,
                tokenOut: token,
                fee: POOL_FEE,
                recipient: DEAD,
                amountIn: buybackIn,
                amountOutMinimum: minTokensOut,
                sqrtPriceLimitX96: 0
            })
        ) returns (uint256 amountOut) {
            tokensBought = amountOut;
            TokenStats storage s = stats[token];
            s.buybackWethSpent += buybackIn;
            s.tokensBurned += tokensBought;
            emit BuybackBurned(token, buybackIn, tokensBought, 0);
        } catch {
            IERC20ApproveLite(WETH).approve(swapRouter, 0);
            pendingBuybackWeth[token] = buybackIn;
            emit BuybackDeferred(token, buybackIn);
        }
    }

    /// @notice The immutable creator fee wallet recorded for `token`
    ///         (zero address when the token is not locked here).
    function creatorWalletOf(address token) external view returns (address) {
        return locks[token].creatorWallet;
    }

    /// @notice The locked position NFT id for `token` (0 when unknown; check
    ///         `creatorWalletOf` for existence).
    function positionIdOf(address token) external view returns (uint256) {
        return locks[token].tokenId;
    }

    /// @notice Cumulative public fee-split stats for `token` in one call.
    function statsOf(address token)
        external
        view
        returns (
            uint256 creatorWethPaid,
            uint256 creatorTokenPaid,
            uint256 buybackWethSpent,
            uint256 tokensBurned,
            uint256 pendingBuyback,
            uint64 lastCollectAt
        )
    {
        TokenStats memory s = stats[token];
        return (
            s.creatorWethPaid,
            s.creatorTokenPaid,
            s.buybackWethSpent,
            s.tokensBurned,
            pendingBuybackWeth[token],
            s.lastCollectAt
        );
    }

    function allLockedTokensLength() external view returns (uint256) {
        return allLockedTokens.length;
    }

    /// @notice ERC-721 receive hook: accept position NFTs ONLY from the
    ///         position manager. Once here, an NFT can never leave — there is
    ///         no transfer/withdraw/decreaseLiquidity path in this contract.
    function onERC721Received(address, address, uint256, bytes calldata)
        external
        view
        returns (bytes4)
    {
        if (msg.sender != positionManager) revert NotPositionManager();
        return this.onERC721Received.selector;
    }
}
Chain explorer1238msChain node88ms