Skip to main content

ZkPadLpLocker

Source: contracts/src/lockers/ZkPadLpLocker.sol · Interface: ILpLocker · Port of Clanker v4 ClankerLpLockerMultiple + ClankerLpLockerFeeConversion to PancakeSwap Infinity CL. GPL-2.0-or-later.

Purpose​

  • Places each launch's supply in 1..7 single-sided positions owned directly in the CLPoolManager (keyed by locker address + salt bytes32(i)). There is no position NFT.
  • Never removes liquidity. The only modifyLiquidity calls are the initial mints (liquidityDelta > 0) and fee pokes (liquidityDelta == 0).
  • Collects LP fees (75% of F) and sends 100% to the launch's FeeVault beneficiary id through FeeVault.depositFromLaunch(token, id, asset, amount), which books them as that launch's credit (the bound on its creator's consolidation rights). By default (FeeIn.Paired) it first converts token-side fees to the paired token through the pool itself; the hook exempts this swap from the zk-pad fee.
  • The conversion only sells what this call's pokes returned, capped at the fees fee-paying swaps earned (IZkPadHook.lpFeesAccrued); anything else owed to the locker (pool donations, settled vault credit) is credited unconverted, so the exemption is never a fee-free exit.
  • Collection is permissionless and also runs automatically from the hook's beforeSwap, so only the previous swaps' fees are ever exposed to the conversion. It runs only when IZkPadHook.conversionAllowed admits its direction (the block's best price for it); otherwise it emits RewardsDeferred and the fees wait for a later block.
  • Token-side fees are settled with their share of the hook's reference value; when the conversion (or, for FeeIn.Both / Token, the pool value) realizes more, 25% of the difference goes to the protocol in the paired token (ProtocolFeeTopUp), so the protocol keeps 25% of what is realized.
  • FeeIn.Both and FeeIn.Token credit the beneficiary in the launched token, which relayers cannot price and consolidation cannot route: the SDK and the wizard require an explicit acknowledgement (self-funded claims).

Types​

enum FeeIn { Both, Paired, Token } // Paired is the default

struct TokenRewardInfo {
address token;
PoolKey poolKey;
bytes32 beneficiaryId;
FeeIn feePreference;
int24[] tickLower; // pool orientation
int24[] tickUpper;
uint128[] liquidity;
}

Functions​

FunctionAccessDescription
placeLiquidity(LockerConfig, PoolConfig, PoolKey, uint256 poolSupply, address token) returns (uint256)factoryPull the supply and mint the positions
collectRewards(address token)anyoneCollect, convert and deposit LP fees (opens a vault lock)
collectRewardsWithoutUnlock(address token)anyone inside a vault lock (the hook calls it from beforeSwap)Same, inside an existing lock; converts no more than collectRewards would
lpFeesConverted(address token) view returns (tokenFees, pairedFees)Cumulative LP fees settled so far, per side (compare with IZkPadHook.lpFeesAccrued)
lpFeeValueSettled(address token) viewPart of IZkPadHook.lpFeeValueAccrued settled with those fees
tokenRewards(address token) viewTokenRewardInfo
factory, vault, poolManager, feeVault, BASIS_POINTS, MAX_LP_POSITIONSviewConfiguration

Position validation (Clanker _mintLiquidity): ticks ordered, inside the usable range, multiples of the tick spacing, no range below the starting tick, each bps > 0, total 10,000, at most 7 positions, and the pool must still be at its starting price.

Events​

EventMeaning
TokenRewardAdded(token, poolKey, poolSupply, beneficiaryId, feePreference, tickLower, tickUpper, positionBps, liquidity)Positions placed
ClaimedRewards(token, beneficiaryId, amount0, amount1)Amounts credited to the FeeVault, after conversion
FeesSwapped(token, rewardToken, amountSwapped, swappedToken, amountOut)Fee-conversion swap
SupplyDustBurned(token, amount)Rounding dust of the supply burned at placement
RewardsDeferred(token)A collection was skipped because an earlier swap in the block moved the price against the conversion
ProtocolFeeTopUp(token, asset, amount)25% of what settled token-side fees realized above their reference value, paid to the factory

Errors​

Unauthorized, OnlyVault, ZeroAddress, InvalidBeneficiary, UnknownToken(token), TokenAlreadyHasRewards, TicksBackwards, TicksOutOfTickBounds, TicksNotMultipleOfTickSpacing, TickRangeLowerThanStartingTick, InvalidPositionBps, ZeroPositionBps, MismatchedPositionInfos, NoPositions, TooManyPositions, ZeroLiquidity, PoolNotAtStartingPrice.