V3 Locker
V3 Locker custodia posiciones de liquidez ERC721 emitidas por contratos INonfungiblePositionManager permitidos. El rango de precio del NFT no puede cambiar durante el bloqueo. Las cuentas autorizadas pueden cobrar comisiones y cualquier usuario puede incrementar la liquidez.
ETERNAL_LOCK es type(uint256).max. Un bloqueo permanente no se puede retirar ni reducir, pero se puede transferir, cobrar comisiones y recibir más liquidez.
Funciones de escritura
lock
function lock(LockParams calldata params)
external
payable
returns (uint256 lockId)
Transfiere el NFT de posición a custodia, cobra las comisiones acumuladas antes del bloqueo, aplica la comisión seleccionada y crea un bloqueo.
| Campo | Tipo | Descripción |
|---|---|---|
params.nftPositionManager | INonfungiblePositionManager | Position Manager permitido. |
params.nft_id | uint256 | ID del NFT propiedad del llamador y ya aprobado. |
params.dustRecipient | address | Destinatario de las comisiones acumuladas antes del bloqueo. |
params.owner | address | Propietario inicial; no puede ser cero. |
params.additionalCollector | address | Collector adicional opcional. |
params.collectAddress | address | Destinatario del ingreso neto del cobro automático; no puede ser cero. |
params.unlockDate | uint256 | Timestamp Unix futuro en segundos, o ETERNAL_LOCK. |
params.countryCode | uint16 | Código aceptado por COUNTRY_LIST. |
params.feeName | string | Opción de comisión, normalmente DEFAULT; se ignora si r no está vacío. |
params.r | bytes[] | Vacío para una comisión nominal; payload de FeeResolver para una dinámica. |
Devuelve lockId, el ID del nuevo bloqueo.
Acceso / payable: propietario del NFT/llamador; payable; nonReentrant.
Position Manager, propietario, dirección de cobro, fecha y país o región deben ser válidos. El NFT debe estar aprobado. Las comisiones ya acumuladas se cobran primero a dustRecipient, evitando cobrarlas como nueva liquidez bloqueada. Una comisión fija nativa exige que msg.value coincida exactamente; una comisión fija ERC20 exige allowance. El ucf almacenado es la tasa de cobro elegida. Se incrementa NONCE y se emite onLock.
Si params.r no está vacío, FEE_RESOLVER.useFee(params.r, msg.sender) proporciona una comisión dinámica. El payload firmado vincula nonce, usuario, cadena y Resolver.
collect
function collect(
uint256 _lockId,
address _recipient,
uint128 _amount0Max,
uint128 _amount1Max
) external returns (
uint256 amount0,
uint256 amount1,
uint256 fee0,
uint256 fee1
)
Cobra comisiones de token0 y token1 de una posición bloqueada.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo cuyas comisiones se cobran. |
_recipient | address | Destinatario del neto para llamadores normales; destinatario de la comisión del protocolo para Auto Collector. |
_amount0Max | uint128 | Cantidad máxima de token0 que se puede cobrar. |
_amount1Max | uint128 | Cantidad máxima de token1 que se puede cobrar. |
| Retorno | Tipo | Descripción |
|---|---|---|
amount0 | uint256 | Cantidad neta de token0 entregada al destinatario del usuario. |
amount1 | uint256 | Cantidad neta de token1 entregada al destinatario del usuario. |
fee0 | uint256 | Comisión de protocolo en token0. |
fee1 | uint256 | Comisión de protocolo en token1. |
Acceso / payable: propietario, additionalCollector o AUTO_COLLECT_ACCOUNT; nonpayable; nonReentrant.
Para un llamador normal, las comisiones del protocolo van a FEE_ADDR_COLLECT y el neto a _recipient. Para AUTO_COLLECT_ACCOUNT, las comisiones van a _recipient y el neto al collectAddress del bloqueo. Si ucf == 0, Position Manager envía todo directamente a _recipient, incluso para Auto Collector. Trate AUTO_COLLECT_ACCOUNT como cuenta de confianza y evite destinatarios cero. Devuelve las cantidades netas amount0/amount1 y las comisiones fee0/fee1.
collectBatchPreview
function collectBatchPreview(
uint256[] calldata lockIds,
address[] calldata recipients,
uint128[] calldata amount0Maxs,
uint128[] calldata amount1Maxs
) external
Simula varias llamadas a collect y devuelve resultados exactos mediante un revert intencional.
| Nombre | Tipo | Descripción |
|---|---|---|
lockIds | uint256[] | Bloqueos que se previsualizan. |
recipients | address[] | Destinatario de cada llamada a collect. |
amount0Maxs | uint128[] | Máximo de token0 para cada bloqueo. |
amount1Maxs | uint128[] | Máximo de token1 para cada bloqueo. |
Acceso / payable: cada elemento usa la misma autorización que collect; nonpayable; nonReentrant.
Los arrays deben tener la misma longitud o revierte con LengthMismatch(). Llámela solo mediante eth_call. Una vista previa correcta revierte con:
error CollectBatchPreviewResult(CollectPreviewItem[] previews);
Cada elemento contiene ID, destinatario, direcciones de tokens, cantidades netas y comisiones. El revert revierte atómicamente el estado de Position Manager, tokens y Locker. Cualquier otro revert indica un fallo real. No transmita esta función como transacción.
increaseLiquidity
function increaseLiquidity(
uint256 _lockId,
INonfungiblePositionManager.IncreaseLiquidityParams calldata params
) external payable returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1
)
Añade liquidez token0/token1.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que recibe liquidez. |
params.tokenId | uint256 | Debe coincidir con el ID del NFT bloqueado. |
params.amount0Desired | uint256 | Máximo de token0 transferido desde el llamador. |
params.amount1Desired | uint256 | Máximo de token1 transferido desde el llamador. |
params.amount0Min | uint256 | Cantidad mínima de token0 utilizada. |
params.amount1Min | uint256 | Cantidad mínima de token1 utilizada. |
params.deadline | uint256 | Fecha límite de Position Manager. |
| Retorno | Tipo | Descripción |
|---|---|---|
liquidity | uint128 | Liquidez añadida. |
amount0 | uint256 | Cantidad de token0 utilizada. |
amount1 | uint256 | Cantidad de token1 utilizada. |
Acceso / payable: cualquier llamador; payable; nonReentrant.
El llamador debe aprobar ambos tokens. Los tokens no utilizados se reembolsan al llamador y se emite onIncreaseLiquidity. La implementación no reenvía msg.value; envíe cero tokens nativos. La interacción directa con Position Manager puede costar menos gas si es compatible.
decreaseLiquidity
function decreaseLiquidity(
uint256 _lockId,
INonfungiblePositionManager.DecreaseLiquidityParams calldata params
) external payable returns (uint256 amount0, uint256 amount1)
Elimina liquidez tras vencer un bloqueo temporal y envía los tokens al propietario.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo cuya liquidez se reduce. |
params.tokenId | uint256 | Debe coincidir con el ID del NFT bloqueado. |
params.liquidity | uint128 | Liquidez que se elimina. |
params.amount0Min | uint256 | Cantidad mínima de token0 acreditada. |
params.amount1Min | uint256 | Cantidad mínima de token1 acreditada. |
params.deadline | uint256 | Fecha límite de Position Manager. |
| Retorno | Tipo | Descripción |
|---|---|---|
amount0 | uint256 | Cantidad de token0 acreditada por decreaseLiquidity. |
amount1 | uint256 | Cantidad de token1 acreditada por decreaseLiquidity. |
Acceso / payable: solo el propietario; payable; nonReentrant.
El bloqueo debe estar vencido y no ser permanente. Primero se cobran todas las comisiones acumuladas mediante la ruta del Locker; luego se cobra al llamador todo lo adeudado por el NFT. No se reenvía msg.value; envíe cero. Emite onDecreaseLiquidity.
relock
function relock(uint256 _lockId, uint256 _unlockDate) external
Extiende el bloqueo o lo hace permanente.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que se extiende. |
_unlockDate | uint256 | Nuevo timestamp en segundos, o ETERNAL_LOCK. |
Acceso / payable: solo el propietario; nonpayable; nonReentrant.
La fecha debe superar el unlockDate actual y block.timestamp; salvo el bloqueo permanente, debe ser menor que 10_000_000_000. El plazo nunca se puede acortar. Emite onRelock.
withdraw
function withdraw(uint256 _lockId, address _receiver) external
Transfiere el NFT completo desde un bloqueo temporal vencido.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que se retira. |
_receiver | address | Destinatario del NFT. |
Acceso / payable: solo el propietario; nonpayable; nonReentrant.
El bloqueo debe estar vencido y no ser permanente. Si ucf > 0, primero se cobran todas las comisiones usando _receiver como destinatario normal. Después se transfiere el NFT, se eliminan los índices y LOCKS, y se emite onWithdraw. Use un receptor compatible con transferencias safe ERC721.
setAdditionalCollector
function setAdditionalCollector(uint256 _lockId, address _additionalCollector) external
Configura la cuenta opcional que puede llamar a collect.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que se configura. |
_additionalCollector | address | Dirección del Collector, o la dirección cero para borrarla. |
Acceso / payable: solo el propietario; nonpayable; nonReentrant. Actualiza el bloqueo y emite onSetAdditionalCollector.
setCollectAddress
function setCollectAddress(uint256 _lockId, address _collectAddress) external
Configura el destinatario de los ingresos netos del cobro automático.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que se configura. |
_collectAddress | address | Destinatario no nulo del cobro automático. |
Acceso / payable: solo el propietario; nonpayable; nonReentrant. Emite onSetCollectAddress.
transferLockOwnership
function transferLockOwnership(uint256 _lockId, address _newOwner) external
Inicia una transferencia de propiedad en dos pasos.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que se transfiere. |
_newOwner | address | Propietario propuesto. |
Acceso / payable: solo el propietario; nonpayable; nonReentrant.
El nuevo propietario debe diferir del llamador. Se acepta la dirección cero, aunque un pending owner cero no puede aceptar. Una propuesta nueva sobrescribe la anterior. Emite onLockOwnershipTransferStarted.
acceptLockOwnership
function acceptLockOwnership(uint256 _lockId, address _collectAddress) external
Acepta la transferencia pendiente y elige la nueva dirección de cobro automático.
| Nombre | Tipo | Descripción |
|---|---|---|
_lockId | uint256 | Bloqueo que se acepta. |
_collectAddress | address | Nueva dirección de cobro almacenada. |
Acceso / payable: solo pending owner; nonpayable; nonReentrant.
Se mueven los índices, se borran pendingOwner y additionalCollector, y se guarda _collectAddress. Esta función acepta una dirección de cobro cero, por lo que el cliente debe rechazarla. Emite onTransferLockOwnership.
Funciones de lectura
getLock / LOCKS
function getLock(uint256 _lockId)
external view returns (Lock memory _lock);
function LOCKS(uint256 lockId) external view returns (
uint256 lock_id,
INonfungiblePositionManager nftPositionManager,
address pool,
uint256 nft_id,
address owner,
address pendingOwner,
address additionalCollector,
address collectAddress,
uint256 unlockDate,
uint16 countryCode,
uint256 ucf
);
Ambos devuelven los mismos campos: getLock devuelve un struct y el getter del mapping una tupla ABI. IDs retirados o desconocidos devuelven un bloqueo con ceros.
| Parámetro | Descripción |
|---|---|
_lockId / lockId | ID del bloqueo que se consulta. |
getLocksLength / NONCE
function getLocksLength() external view returns (uint256);
function NONCE() external view returns (uint256);
Ambos devuelven el siguiente ID, incluidos los bloqueos históricos retirados. No representan el número activo.
Enumeración de usuarios
function getNumUserLocks(address _user) external view returns (uint256);
function getUserLockAtIndex(address _user, uint256 _index)
external view returns (Lock memory);
| Parámetro | Descripción |
|---|---|
_user | Propietario cuyo conjunto de bloqueos activos se consulta. |
_index | Índice activo desde cero; fuera de rango revierte. |
La primera devuelve el número activo. La segunda resuelve el ID del índice y devuelve su bloqueo.
Consultas de comisiones
function getFee(string memory _name) public view returns (FeeStruct memory);
function getFeeOptionAtIndex(uint256 _index)
external view returns (FeeStruct memory);
function getFeeOptionLength() external view returns (uint256);
| Parámetro | Descripción |
|---|---|
_name | Nombre exacto de la opción; un nombre desconocido revierte. |
_index | Índice desde cero del conjunto de comisiones; un índice inválido revierte. |
FeeStruct incluye name, lpFee, collectFee, flatFee y flatFeeToken. Las opciones pueden cambiar inmediatamente; léalas justo antes de bloquear.
nftPositionManagerIsAllowed
function nftPositionManagerIsAllowed(address _nftPositionManager)
external view returns (bool);
Indica si lock puede usar ese Position Manager.
Getters de configuración pública
function ETERNAL_LOCK() external view returns (uint256);
function FEE_DENOMINATOR() external view returns (uint256);
function COUNTRY_LIST() external view returns (address);
function FEE_RESOLVER() external view returns (address);
function AUTO_COLLECT_ACCOUNT() external view returns (address);
function FEE_ADDR_LP() external view returns (address);
function FEE_ADDR_COLLECT() external view returns (address);
function owner() external view returns (address);
Exponen constantes, dependencias, direcciones privilegiadas y la propiedad del contrato en dos pasos.
Eventos
onLock
event onLock(uint256 lock_id, address nftPositionManager, uint256 nft_id, address owner, address additionalCollector, address collectAddress, uint256 unlockDate, uint16 countryCode, uint256 collectFee, address poolAddress, INonfungiblePositionManager.Position position);
Se emite cuando lock crea un bloqueo. Incluye IDs, cuentas, condiciones de desbloqueo, tasa ucf, dirección del pool y snapshot completo de Position.
| Parámetro | Descripción |
|---|---|
lock_id | ID del nuevo bloqueo. |
nftPositionManager | Position Manager que define el NFT. |
nft_id | ID del NFT de posición. |
owner | Propietario inicial del bloqueo. |
additionalCollector | Collector opcional. |
collectAddress | Destinatario del ingreso neto del cobro automático. |
unlockDate | Timestamp de desbloqueo o ETERNAL_LOCK. |
countryCode | Código de país o región validado. |
collectFee | Tasa ucf almacenada. |
poolAddress | Pool de Factory correspondiente a la posición. |
position | Snapshot completo de Position de Position Manager. |
onWithdraw
event onWithdraw(uint256 lock_id, address owner, address receiver);
Se emite antes de eliminar el estado del bloqueo retirado.
| Parámetro | Descripción |
|---|---|
lock_id | Bloqueo retirado. |
owner | Propietario del bloqueo. |
receiver | Destinatario del NFT. |
onLockOwnershipTransferStarted
event onLockOwnershipTransferStarted(uint256 lockId, address currentOwner, address pendingOwner);
Se emite cuando el propietario actual propone uno nuevo.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo en transferencia. |
currentOwner | Propietario actual. |
pendingOwner | Propietario propuesto. |
onTransferLockOwnership
event onTransferLockOwnership(uint256 lockId, address oldOwner, address newOwner, address newCollectAddress);
Se emite cuando el pending owner acepta la transferencia.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo transferido. |
oldOwner | Propietario anterior. |
newOwner | Nuevo propietario que acepta la transferencia. |
newCollectAddress | Dirección de cobro proporcionada al aceptar. |
onSetAdditionalCollector
event onSetAdditionalCollector(uint256 lockId, address additionalCollector);
Se emite cuando el propietario cambia el Additional Collector, que puede ser cero.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo actualizado. |
additionalCollector | Nuevo Collector, que puede ser la dirección cero. |
onSetCollectAddress
event onSetCollectAddress(uint256 lockId, address collectAddress);
Se emite cuando el propietario cambia el destinatario no nulo del cobro automático.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo actualizado. |
collectAddress | Nuevo destinatario no nulo. |
onRelock
event onRelock(uint256 lockId, uint256 unlockDate);
Se emite después de extender un bloqueo.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo extendido. |
unlockDate | Nuevo timestamp de desbloqueo. |
onIncreaseLiquidity
event onIncreaseLiquidity(uint256 lockId);
Se emite después de añadir liquidez mediante el wrapper del Locker.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo cuya liquidez aumentó. |
onDecreaseLiquidity
event onDecreaseLiquidity(uint256 lockId);
Se emite después de reducir la liquidez de un bloqueo vencido mediante el Locker.
| Parámetro | Descripción |
|---|---|
lockId | Bloqueo cuya liquidez disminuyó. |
Errores
Errores de negocio del Locker
| Error / Revert | Funciones | Activación |
|---|---|---|
OWNER CANNOT = address(0) | lock | params.owner es cero. |
COLLECT_ADDR | lock, setCollectAddress | collectAddress es cero. acceptLockOwnership no realiza esta comprobación. |
MILLISECONDS | lock, relock | Timestamp normal al menos 10_000_000_000. |
DATE PASSED | lock, relock | La fecha no es posterior al bloque actual. |
COUNTRY | lock | countryCode no supera COUNTRY_LIST. |
INVALID NFT POSITION MANAGER | lock | Position Manager no permitido. |
NOT FOUND | lock, getFee | La opción nominal no existe. |
FLAT FEE | lock | msg.value no coincide exactamente. |
Gas token transfer failed | lock, adminRefundEth | Falla la transferencia nativa. |
OWNER | collect, collectBatchPreview, funciones de gestión | El llamador no es un Owner, Additional Collector, Auto Collector o pending Owner autorizado. |
NFT ID | increaseLiquidity, decreaseLiquidity | params.tokenId difiere del nft_id. |
ETERNAL_LOCK | decreaseLiquidity, withdraw | Operación sobre un bloqueo permanente. |
NOT YET | decreaseLiquidity, withdraw | El bloqueo aún no venció. |
DATE | relock | La nueva fecha no supera el unlockDate. |
SAME OWNER | transferLockOwnership | _newOwner es el Owner actual. |
L | setUCF | _ucf nuevo no es menor que la tasa actual. |
DEFAULT | removeFee | Intento de eliminar DEFAULT. |
Fee not exists | removeFee | La opción no existe. |
Errores personalizados de vista previa
error CollectBatchPreviewResult(CollectPreviewItem[] previews);
error LengthMismatch();
| Custom Error | Significado |
|---|---|
CollectBatchPreviewResult(...) | Payload de éxito esperado de collectBatchPreview. Decodifique previews como resultado. |
LengthMismatch() | Las longitudes de lockIds, recipients, amount0Maxs y amount1Maxs son distintas. |
Errores externos y heredados
| Error / Revert | Activación |
|---|---|
STF | Falla safeTransferFrom, normalmente por saldo o allowance. |
ST | Falla safeTransfer. |
SA | Falla safeApprove. |
Ownable: caller is not the owner | Una cuenta que no es owner llama a administración. |
ReentrancyGuard: reentrant call | Reentrada en una función nonReentrant. |
Panic(0x11) | Underflow u overflow aritmético. |