Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: remove double call to modifyLiquidity when user add/remove liquidity #35

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1 @@
54579
54723
2 changes: 1 addition & 1 deletion .forge-snapshots/BinFungibleTokenTest#testBurn.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
26887
26896
2 changes: 1 addition & 1 deletion .forge-snapshots/BinFungibleTokenTest#testMint.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
67685
67373
2 changes: 1 addition & 1 deletion .forge-snapshots/NonfungiblePositionManager#collect.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
265629
265663
Original file line number Diff line number Diff line change
@@ -1 +1 @@
176568
161440
Original file line number Diff line number Diff line change
@@ -1 +1 @@
210284
195159
2 changes: 1 addition & 1 deletion .forge-snapshots/NonfungiblePositionManager#mint.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
609324
607379
2 changes: 1 addition & 1 deletion src/pool-cl/NonfungiblePositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ contract NonfungiblePositionManager is
uint128 tokensOwed1 = nftPositionCache.tokensOwed1;

if (nftPositionCache.liquidity > 0) {
resetAccumulatedFee(poolKey, nftPositionCache.tickLower, nftPositionCache.tickUpper);
mintAccumulatedPositionFee(poolKey, nftPositionCache.tickLower, nftPositionCache.tickUpper);

// todo: about the salt
CLPosition.Info memory poolManagerPositionInfo = poolManager.getPosition(
Expand Down
45 changes: 28 additions & 17 deletions src/pool-cl/base/LiquidityManagement.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,45 +44,52 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay
uint256 amount1Min;
}

/// @dev Since in v4 `modifyLiquidity` accumulated fee are claimed and
// resynced by default, which can mixup with user's actual settlement
// for update liquidity, we claim the fee before further action to avoid this.
function resetAccumulatedFee(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) internal {
/// @notice Claim accumulated fees from the position and mint them to the NFP contract
function mintAccumulatedPositionFee(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) internal {
CLPosition.Info memory poolManagerPositionInfo =
poolManager.getPosition(poolKey.toId(), address(this), tickLower, tickUpper, SALT_0);

if (poolManagerPositionInfo.liquidity > 0) {
// todo: can we avoid this resetAccumulatedFee call?
(, BalanceDelta feeDelta) = poolManager.modifyLiquidity(
poolKey, ICLPoolManager.ModifyLiquidityParams(tickLower, tickUpper, 0, SALT_0), ""
);

if (feeDelta.amount0() > 0) {
vault.mint(address(this), poolKey.currency0, uint256(int256(feeDelta.amount0())));
}
mintFeeDelta(poolKey, feeDelta);
}
}

if (feeDelta.amount1() > 0) {
vault.mint(address(this), poolKey.currency1, uint256(int256(feeDelta.amount1())));
}
/// @dev Mint accumulated fee to the contract so user can perform collect() at a later stage
function mintFeeDelta(PoolKey memory poolKey, BalanceDelta feeDelta) internal {
if (feeDelta.amount0() > 0) {
vault.mint(address(this), poolKey.currency0, uint256(int256(feeDelta.amount0())));
}

if (feeDelta.amount1() > 0) {
vault.mint(address(this), poolKey.currency1, uint256(int256(feeDelta.amount1())));
}
}

/// @return liquidity The amount of liquidity added to the position
/// @return delta The amount of token0 and token1 from liquidity additional. Does not include the fee accumulated in the position.
function addLiquidity(AddLiquidityParams memory params) internal returns (uint128 liquidity, BalanceDelta delta) {
resetAccumulatedFee(params.poolKey, params.tickLower, params.tickUpper);

(uint160 sqrtPriceX96,,,) = poolManager.getSlot0(params.poolKey.toId());
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(params.tickLower);
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(params.tickUpper);
liquidity = LiquidityAmounts.getLiquidityForAmounts(
sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, params.amount0Desired, params.amount1Desired
);

(delta,) = poolManager.modifyLiquidity(
BalanceDelta feeDelta;
(delta, feeDelta) = poolManager.modifyLiquidity(
params.poolKey,
ICLPoolManager.ModifyLiquidityParams(params.tickLower, params.tickUpper, int256(uint256(liquidity)), SALT_0),
""
);

/// @dev `delta` return value of modifyLiquidity is inclusive of fee. Mint the `feeDelta` to nfp contract so subtract from `delta`
delta = delta - feeDelta;
mintFeeDelta(params.poolKey, feeDelta);

/// @dev amount0 & amount1 cant be positive here since LPing has been claimed
if (
uint256(uint128(-delta.amount0())) < params.amount0Min
Expand All @@ -92,17 +99,21 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay
}
}

/// @return delta The amount of token0 and token1 from liquidity removal. Does not include the fee accumulated in the position.
function removeLiquidity(RemoveLiquidityParams memory params) internal returns (BalanceDelta delta) {
resetAccumulatedFee(params.poolKey, params.tickLower, params.tickUpper);

(delta,) = poolManager.modifyLiquidity(
BalanceDelta feeDelta;
(delta, feeDelta) = poolManager.modifyLiquidity(
params.poolKey,
ICLPoolManager.ModifyLiquidityParams(
params.tickLower, params.tickUpper, -int256(uint256(params.liquidity)), SALT_0
),
""
);

/// @dev `delta` return value of modifyLiquidity is inclusive of fee. Mint the `feeDelta` to nfp contract so subtract from `delta`
delta = delta - feeDelta;
mintFeeDelta(params.poolKey, feeDelta);

/// @dev amount0 & amount1 must be positive here since LPing has been claimed
if (
uint256(uint128(delta.amount0())) < params.amount0Min
Expand Down
Loading