본문으로 건너뛰기

V3 Locker

V3 Locker는 허용 목록에 등록된 INonfungiblePositionManager가 발행한 ERC721 유동성 포지션을 보관합니다. 락 중에는 NFT 가격 범위를 변경할 수 없습니다. 승인된 계정은 수수료를 수집할 수 있고 모든 사용자가 유동성을 추가할 수 있습니다.

ETERNAL_LOCKtype(uint256).max입니다. 영구 락은 출금하거나 유동성을 줄일 수 없지만 이전, 수수료 수집, 유동성 추가는 가능합니다.

쓰기 함수

lock

function lock(LockParams calldata params)
external
payable
returns (uint256 lockId)

포지션 NFT를 보관하고 락 전에 누적된 수수료를 수집한 뒤 선택한 락 수수료를 적용해 락을 생성합니다.

필드타입설명
params.nftPositionManagerINonfungiblePositionManager허용 목록 Position Manager.
params.nft_iduint256호출자가 소유하고 승인한 NFT ID.
params.dustRecipientaddress락 전 누적 수수료 수령인.
params.owneraddress초기 락 Owner. 0 주소 불가.
params.additionalCollectoraddress선택적 Additional Collector.
params.collectAddressaddress자동 수집 순수익 수령인. 0 주소 불가.
params.unlockDateuint256초 단위 미래 Unix 시각 또는 ETERNAL_LOCK.
params.countryCodeuint16COUNTRY_LIST가 허용하는 코드.
params.feeNamestring일반적으로 DEFAULT. r이 비어 있지 않으면 무시됩니다.
params.rbytes[]이름 기반 수수료에는 빈 배열, 동적 수수료에는 FeeResolver payload.

새 락 ID lockId를 반환합니다.

접근 / payable: NFT Owner/호출자; payable; nonReentrant.

Position Manager, Owner, 수집 주소, 날짜와 국가/지역이 유효해야 하며 NFT가 승인되어야 합니다. 기존 누적 수수료는 먼저 dustRecipient로 수집되어 새 락 유동성 수수료 계산에서 제외됩니다. 네이티브 고정 수수료는 msg.value가 정확히 일치해야 하며 ERC20 고정 수수료에는 allowance가 필요합니다. 저장되는 ucf는 선택한 수집 수수료율입니다. NONCE를 증가시키고 onLock을 발생시킵니다.

params.r이 비어 있지 않으면 FEE_RESOLVER.useFee(params.r, msg.sender)가 동적 수수료를 제공합니다. 서명 payload는 nonce, 사용자, 체인과 Resolver를 바인딩합니다.

collect

function collect(
uint256 _lockId,
address _recipient,
uint128 _amount0Max,
uint128 _amount1Max
) external returns (
uint256 amount0,
uint256 amount1,
uint256 fee0,
uint256 fee1
)

락된 포지션에서 token0/token1 수수료를 수집합니다.

이름타입설명
_lockIduint256수수료를 수집할 락.
_recipientaddress일반 호출자의 순수익 수령인. Auto Collector에서는 프로토콜 수수료 수령인.
_amount0Maxuint128token0 최대 수집량.
_amount1Maxuint128token1 최대 수집량.
반환값타입설명
amount0uint256사용자 측 수령인에게 전달되는 token0 순수량.
amount1uint256사용자 측 수령인에게 전달되는 token1 순수량.
fee0uint256token0 프로토콜 수수료.
fee1uint256token1 프로토콜 수수료.

접근 / payable: 락 Owner, additionalCollector 또는 AUTO_COLLECT_ACCOUNT; nonpayable; nonReentrant.

일반 호출에서는 프로토콜 수수료를 FEE_ADDR_COLLECT로, 순수익을 _recipient로 보냅니다. AUTO_COLLECT_ACCOUNT에서는 수수료를 _recipient로, 순수익을 락의 collectAddress로 보냅니다. ucf == 0이면 Auto Collector 호출을 포함해 Position Manager가 전액을 _recipient로 직접 보냅니다. AUTO_COLLECT_ACCOUNT를 신뢰 계정으로 취급하고 0 수령인은 피해야 합니다. 순수량 amount0/amount1과 수수료 fee0/fee1을 반환합니다.

collectBatchPreview

function collectBatchPreview(
uint256[] calldata lockIds,
address[] calldata recipients,
uint128[] calldata amount0Maxs,
uint128[] calldata amount1Maxs
) external

여러 collect 호출을 시뮬레이션하고 의도적인 revert로 정확한 결과를 반환합니다.

이름타입설명
lockIdsuint256[]미리 볼 락.
recipientsaddress[]collect 호출의 수령인 매개변수.
amount0Maxsuint128[]각 락의 token0 최대값.
amount1Maxsuint128[]각 락의 token1 최대값.

접근 / payable: 각 항목은 collect와 같은 권한을 사용; nonpayable; nonReentrant.

배열 길이가 다르면 LengthMismatch()로 revert합니다. eth_call로만 호출하세요. 성공한 미리보기는 다음 오류로 revert합니다.

error CollectBatchPreviewResult(CollectPreviewItem[] previews);

각 항목에는 락 ID, 수령인, 토큰 주소, 순수량과 수수료가 포함됩니다. revert가 Position Manager, 토큰과 Locker 상태를 원자적으로 되돌립니다. 다른 revert는 실제 실패입니다. 트랜잭션으로 전송하지 마세요.

increaseLiquidity

function increaseLiquidity(
uint256 _lockId,
INonfungiblePositionManager.IncreaseLiquidityParams calldata params
) external payable returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1
)

token0/token1 유동성을 추가합니다.

이름타입설명
_lockIduint256유동성을 받을 락.
params.tokenIduint256락의 NFT ID와 같아야 합니다.
params.amount0Desireduint256호출자에게서 전송할 token0 최대 수량.
params.amount1Desireduint256호출자에게서 전송할 token1 최대 수량.
params.amount0Minuint256token0 최소 사용량.
params.amount1Minuint256token1 최소 사용량.
params.deadlineuint256Position Manager 기한.
반환값타입설명
liquidityuint128추가된 유동성.
amount0uint256사용된 token0 수량.
amount1uint256사용된 token1 수량.

접근 / payable: 모든 호출자; payable; nonReentrant.

두 토큰을 모두 승인해야 합니다. 미사용 토큰은 호출자에게 반환되고 onIncreaseLiquidity가 발생합니다. 구현은 msg.value를 전달하지 않으므로 네이티브 토큰은 0을 보내야 합니다. 호환된다면 Position Manager 직접 호출이 Gas를 절약할 수 있습니다.

decreaseLiquidity

function decreaseLiquidity(
uint256 _lockId,
INonfungiblePositionManager.DecreaseLiquidityParams calldata params
) external payable returns (uint256 amount0, uint256 amount1)

기간제 락 만료 후 유동성을 제거하고 토큰을 Owner에게 보냅니다.

이름타입설명
_lockIduint256유동성을 줄일 락.
params.tokenIduint256락의 NFT ID와 같아야 합니다.
params.liquidityuint128제거할 유동성.
params.amount0Minuint256반영될 token0 최소 수량.
params.amount1Minuint256반영될 token1 최소 수량.
params.deadlineuint256Position Manager 기한.
반환값타입설명
amount0uint256decreaseLiquidity가 반영한 token0 수량.
amount1uint256decreaseLiquidity가 반영한 token1 수량.

접근 / payable: 락 Owner만; payable; nonReentrant.

만료된 비영구 락이어야 합니다. 현재 누적 수수료를 Locker 수수료 경로로 먼저 수집한 뒤 NFT가 지급할 모든 토큰을 호출자에게 수집합니다. msg.value는 전달되지 않으므로 0을 보내세요. onDecreaseLiquidity를 발생시킵니다.

relock

function relock(uint256 _lockId, uint256 _unlockDate) external

기간을 연장하거나 영구 락으로 만듭니다.

이름타입설명
_lockIduint256연장할 락.
_unlockDateuint256초 단위 새 타임스탬프 또는 ETERNAL_LOCK.

접근 / payable: 락 Owner만; nonpayable; nonReentrant.

새 날짜는 현재 unlockDateblock.timestamp보다 모두 커야 하고 영구 락 이외에는 10_000_000_000보다 작아야 합니다. 기간을 줄일 수 없습니다. onRelock을 발생시킵니다.

withdraw

function withdraw(uint256 _lockId, address _receiver) external

만료된 기간제 락에서 전체 NFT를 이전합니다.

이름타입설명
_lockIduint256출금할 락.
_receiveraddressNFT 수령인.

접근 / payable: 락 Owner만; nonpayable; nonReentrant.

만료된 비영구 락이어야 합니다. ucf > 0이면 _receiver를 일반 수령인으로 사용해 모든 수수료를 먼저 수집합니다. 이후 NFT를 이전하고 사용자 인덱스와 LOCKS를 삭제하며 onWithdraw을 발생시킵니다. safe ERC721 전송을 받을 수 있는 주소를 사용하세요.

setAdditionalCollector

function setAdditionalCollector(uint256 _lockId, address _additionalCollector) external

collect를 호출할 수 있는 선택 계정을 설정합니다.

이름타입설명
_lockIduint256설정할 락.
_additionalCollectoraddressCollector 주소. 0 주소로 해제할 수 있습니다.

접근 / payable: 락 Owner만; nonpayable; nonReentrant. 락을 업데이트하고 onSetAdditionalCollector를 발생시킵니다.

setCollectAddress

function setCollectAddress(uint256 _lockId, address _collectAddress) external

자동 수집 순수익 수령인을 설정합니다.

이름타입설명
_lockIduint256설정할 락.
_collectAddressaddress0이 아닌 자동 수집 수령인.

접근 / payable: 락 Owner만; nonpayable; nonReentrant. onSetCollectAddress를 발생시킵니다.

transferLockOwnership

function transferLockOwnership(uint256 _lockId, address _newOwner) external

2단계 소유권 이전을 시작합니다.

이름타입설명
_lockIduint256이전할 락.
_newOwneraddress제안된 Owner.

접근 / payable: 락 Owner만; nonpayable; nonReentrant.

새 Owner는 호출자와 달라야 합니다. 0 주소를 허용하지만 0 pending Owner는 수락할 수 없습니다. 새 제안은 기존 pending Owner를 덮어씁니다. onLockOwnershipTransferStarted를 발생시킵니다.

acceptLockOwnership

function acceptLockOwnership(uint256 _lockId, address _collectAddress) external

대기 중 이전을 수락하고 새 자동 수집 주소를 선택합니다.

이름타입설명
_lockIduint256수락할 락.
_collectAddressaddress새로 저장할 수집 주소.

접근 / payable: pending Owner만; nonpayable; nonReentrant.

사용자 인덱스를 이동하고 pendingOwneradditionalCollector를 지운 뒤 _collectAddress를 저장합니다. 이 함수는 0 수집 주소를 허용하므로 클라이언트에서 거부해야 합니다. onTransferLockOwnership을 발생시킵니다.

읽기 함수

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
);

두 함수는 같은 필드를 반환합니다. getLock은 struct, mapping Getter는 ABI tuple입니다. 출금했거나 알 수 없는 ID는 모두 0인 락을 반환합니다.

매개변수설명
_lockId / lockId조회할 락 ID.

getLocksLength / NONCE

function getLocksLength() external view returns (uint256);
function NONCE() external view returns (uint256);

두 함수 모두 과거 기록을 포함한 다음 락 ID를 반환하며 활성 락 수가 아닙니다.

사용자 열거

function getNumUserLocks(address _user) external view returns (uint256);
function getUserLockAtIndex(address _user, uint256 _index)
external view returns (Lock memory);
매개변수설명
_user활성 락 집합을 조회할 Owner.
_index0부터 시작하는 활성 집합 인덱스. 범위를 벗어나면 revert합니다.

첫 함수는 활성 락 수를, 두 번째는 인덱스에 해당하는 ID의 락을 반환합니다.

수수료 조회

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);
매개변수설명
_name정확한 수수료 옵션 이름. 알 수 없는 이름은 revert합니다.
_index0부터 시작하는 수수료 집합 인덱스. 잘못된 값은 revert합니다.

FeeStructname, lpFee, collectFee, flatFee, flatFeeToken을 포함합니다. 옵션은 즉시 변경될 수 있으므로 락 직전에 읽어야 합니다.

nftPositionManagerIsAllowed

function nftPositionManagerIsAllowed(address _nftPositionManager)
external view returns (bool);

해당 Position Manager를 lock에서 사용할 수 있는지 반환합니다.

공개 설정 Getter

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);

상수, 외부 의존성, 권한 주소와 2단계 컨트랙트 소유권을 공개합니다.

이벤트

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);

lock이 락을 생성할 때 발생합니다. ID, 계정, 해제 조건, ucf 비율, Pool 주소와 전체 Position snapshot을 포함합니다.

매개변수설명
lock_id새 락 ID.
nftPositionManagerNFT를 정의하는 Position Manager.
nft_id포지션 NFT ID.
owner초기 락 Owner.
additionalCollector선택적 Collector.
collectAddress자동 수집 순수익 수령인.
unlockDate해제 타임스탬프 또는 ETERNAL_LOCK.
countryCode검증된 국가/지역 코드.
collectFee저장된 ucf 비율.
poolAddress포지션에 해당하는 Factory Pool.
positionPosition Manager의 전체 Position snapshot.

onWithdraw

event onWithdraw(uint256 lock_id, address owner, address receiver);

출금한 락 상태를 삭제하기 전에 발생합니다.

매개변수설명
lock_id출금된 락.
owner락 Owner.
receiverNFT 수령인.

onLockOwnershipTransferStarted

event onLockOwnershipTransferStarted(uint256 lockId, address currentOwner, address pendingOwner);

현재 Owner가 새 Owner를 제안할 때 발생합니다.

매개변수설명
lockId이전 중인 락.
currentOwner현재 Owner.
pendingOwner제안된 Owner.

onTransferLockOwnership

event onTransferLockOwnership(uint256 lockId, address oldOwner, address newOwner, address newCollectAddress);

pending Owner가 이전을 수락할 때 발생합니다.

매개변수설명
lockId이전된 락.
oldOwner이전 Owner.
newOwner이전을 수락한 새 Owner.
newCollectAddress수락 시 제공한 수집 주소.

onSetAdditionalCollector

event onSetAdditionalCollector(uint256 lockId, address additionalCollector);

Owner가 Additional Collector를 변경할 때 발생합니다. 0 주소도 가능합니다.

매개변수설명
lockId업데이트된 락.
additionalCollector새 Collector. 0 주소도 가능합니다.

onSetCollectAddress

event onSetCollectAddress(uint256 lockId, address collectAddress);

Owner가 0이 아닌 자동 수집 주소를 변경할 때 발생합니다.

매개변수설명
lockId업데이트된 락.
collectAddress새 0이 아닌 수령인.

onRelock

event onRelock(uint256 lockId, uint256 unlockDate);

락 기간을 연장한 후 발생합니다.

매개변수설명
lockId연장된 락.
unlockDate새 해제 타임스탬프.

onIncreaseLiquidity

event onIncreaseLiquidity(uint256 lockId);

Locker wrapper로 유동성을 추가한 후 발생합니다.

매개변수설명
lockId유동성이 증가한 락.

onDecreaseLiquidity

event onDecreaseLiquidity(uint256 lockId);

만료된 락에서 Locker를 통해 유동성을 줄인 후 발생합니다.

매개변수설명
lockId유동성이 감소한 락.

오류

Locker 비즈니스 오류

Error / Revert관련 함수조건
OWNER CANNOT = address(0)lockparams.owner가 0입니다.
COLLECT_ADDRlock, setCollectAddresscollectAddress가 0입니다. acceptLockOwnership은 이 검사를 수행하지 않습니다.
MILLISECONDSlock, relock일반 시각이 10_000_000_000 이상입니다.
DATE PASSEDlock, relock시각이 현재보다 늦지 않습니다.
COUNTRYlockcountryCode 검증 실패.
INVALID NFT POSITION MANAGERlockPosition Manager가 허용되지 않았습니다.
NOT FOUNDlock, getFee이름 기반 수수료가 없습니다.
FLAT FEElockmsg.value가 정확히 일치하지 않습니다.
Gas token transfer failedlock, adminRefundEth네이티브 전송 실패.
OWNERcollect, collectBatchPreview, 락 관리 함수호출자가 허용된 Owner, Additional Collector, Auto Collector 또는 pending Owner가 아닙니다.
NFT IDincreaseLiquidity, decreaseLiquidityparams.tokenIdnft_id와 다릅니다.
ETERNAL_LOCKdecreaseLiquidity, withdraw영구 락에 대한 작업입니다.
NOT YETdecreaseLiquidity, withdraw락이 아직 만료되지 않았습니다.
DATErelock새 시각이 unlockDate보다 크지 않습니다.
SAME OWNERtransferLockOwnership_newOwner가 현재 Owner입니다.
LsetUCF_ucf가 현재 비율보다 작지 않습니다.
DEFAULTremoveFeeDEFAULT 삭제 시도.
Fee not existsremoveFee옵션이 없습니다.

배치 미리보기 사용자 정의 오류

error CollectBatchPreviewResult(CollectPreviewItem[] previews);
error LengthMismatch();
Custom Error의미
CollectBatchPreviewResult(...)collectBatchPreview의 예상 성공 payload. previews를 결과로 디코딩합니다.
LengthMismatch()lockIds, recipients, amount0Maxs, amount1Maxs 길이가 일치하지 않습니다.

외부 및 상속 오류

Error / Revert조건
STFsafeTransferFrom 실패. 일반적으로 잔액 또는 allowance 부족.
STsafeTransfer 실패.
SAsafeApprove 실패.
Ownable: caller is not the ownerOwner가 아닌 계정의 관리 함수 호출.
ReentrancyGuard: reentrant callnonReentrant 함수 재진입.
Panic(0x11)산술 underflow/overflow.