diff --git a/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToMsgSender.snap b/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToMsgSender.snap index 89920090c..78e17c574 100644 --- a/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToMsgSender.snap +++ b/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToMsgSender.snap @@ -1 +1 @@ -129465 \ No newline at end of file +129314 \ No newline at end of file diff --git a/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToSpecifiedAddress.snap b/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToSpecifiedAddress.snap index bd98929bb..62a95b03c 100644 --- a/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToSpecifiedAddress.snap +++ b/.forge-snapshots/Payments_swap_settleFromCaller_takeAllToSpecifiedAddress.snap @@ -1 +1 @@ -131383 \ No newline at end of file +131232 \ No newline at end of file diff --git a/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToMsgSender.snap b/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToMsgSender.snap index 9f1afb339..5aea292f0 100644 --- a/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToMsgSender.snap +++ b/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToMsgSender.snap @@ -1 +1 @@ -123588 \ No newline at end of file +123437 \ No newline at end of file diff --git a/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToSpecifiedAddress.snap b/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToSpecifiedAddress.snap index 7e4d7fb0b..11607e19c 100644 --- a/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToSpecifiedAddress.snap +++ b/.forge-snapshots/Payments_swap_settleWithBalance_takeAllToSpecifiedAddress.snap @@ -1 +1 @@ -123730 \ No newline at end of file +123579 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index 6479cc20a..9d29ee915 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -47152 \ No newline at end of file +50179 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_empty_native.snap b/.forge-snapshots/PositionManager_burn_empty_native.snap index 074ac1bc5..9d29ee915 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -46970 \ No newline at end of file +50179 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native_withClose.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native_withClose.snap index b6a4062a1..e93b3042e 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native_withClose.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native_withClose.snap @@ -1 +1 @@ -122397 \ No newline at end of file +125084 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native_withTakePair.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native_withTakePair.snap index 5eb3b7616..9d26475b0 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native_withTakePair.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native_withTakePair.snap @@ -1 +1 @@ -121968 \ No newline at end of file +124645 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_withClose.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_withClose.snap index 3fbd663dd..73668a96c 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_withClose.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_withClose.snap @@ -1 +1 @@ -129430 \ No newline at end of file +131935 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_withTakePair.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_withTakePair.snap index d21b4ba5d..277fd2ec4 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_withTakePair.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_withTakePair.snap @@ -1 +1 @@ -129000 \ No newline at end of file +131496 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index 2331f0e72..218fca4c5 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -141457 \ No newline at end of file +145670 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index f46b7a3c9..8264a7e8d 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -150248 \ No newline at end of file +154233 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_withClose.snap b/.forge-snapshots/PositionManager_collect_withClose.snap index f46b7a3c9..8264a7e8d 100644 --- a/.forge-snapshots/PositionManager_collect_withClose.snap +++ b/.forge-snapshots/PositionManager_collect_withClose.snap @@ -1 +1 @@ -150248 \ No newline at end of file +154233 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_withTakePair.snap b/.forge-snapshots/PositionManager_collect_withTakePair.snap index 0986a117d..a38102828 100644 --- a/.forge-snapshots/PositionManager_collect_withTakePair.snap +++ b/.forge-snapshots/PositionManager_collect_withTakePair.snap @@ -1 +1 @@ -149699 \ No newline at end of file +153696 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index 8e6d46423..39d397a88 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -108111 \ No newline at end of file +111481 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_withClose.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_withClose.snap index 72ccfd2ec..a873cbbd3 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_withClose.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_withClose.snap @@ -1 +1 @@ -115144 \ No newline at end of file +119114 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_withTakePair.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_withTakePair.snap index 69bb06d35..88a8f520d 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_withTakePair.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_withTakePair.snap @@ -1 +1 @@ -114704 \ No newline at end of file +118577 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index 70af78d66..359fe2702 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -133217 \ No newline at end of file +134624 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap index 36c2096e0..4eea84284 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -126002 \ No newline at end of file +127773 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap index 784739a55..f1fb30312 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -127816 \ No newline at end of file +131801 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_take_take.snap b/.forge-snapshots/PositionManager_decrease_take_take.snap index d0ada0254..97ad2019a 100644 --- a/.forge-snapshots/PositionManager_decrease_take_take.snap +++ b/.forge-snapshots/PositionManager_decrease_take_take.snap @@ -1 +1 @@ -115704 \ No newline at end of file +119690 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withClose.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withClose.snap index c34d743e8..93f475975 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withClose.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withClose.snap @@ -1 +1 @@ -154710 \ No newline at end of file +158393 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withSettlePair.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withSettlePair.snap index 41b64e179..5fbf68fbb 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withSettlePair.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20_withSettlePair.snap @@ -1 +1 @@ -153768 \ No newline at end of file +157475 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index 1eb854016..e3e91ac83 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -136161 \ No newline at end of file +140223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index df828bd4a..4fbebd561 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -132017 \ No newline at end of file +136002 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index feda9c142..55dc7fa48 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -172721 \ No newline at end of file +176706 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompound_clearExcess.snap b/.forge-snapshots/PositionManager_increase_autocompound_clearExcess.snap index c28748a2a..38be7685f 100644 --- a/.forge-snapshots/PositionManager_increase_autocompound_clearExcess.snap +++ b/.forge-snapshots/PositionManager_increase_autocompound_clearExcess.snap @@ -1 +1 @@ -143403 \ No newline at end of file +147388 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index c0208a913..e7fafb69b 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -339859 \ No newline at end of file +364087 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep_withClose.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep_withClose.snap index 7d4a09892..1883afaae 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep_withClose.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep_withClose.snap @@ -1 +1 @@ -348239 \ No newline at end of file +372467 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep_withSettlePair.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep_withSettlePair.snap index cd701aeae..d0623c31e 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep_withSettlePair.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep_withSettlePair.snap @@ -1 +1 @@ -347605 \ No newline at end of file +371833 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index 9720dd080..3e79982be 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -318177 \ No newline at end of file +316932 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index c985771e3..4f8b1b2c0 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -318847 \ No newline at end of file +317602 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index c2bfd79d8..c154222f2 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -244416 \ No newline at end of file +243171 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap index 7062038a8..efcdb2b87 100644 --- a/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap +++ b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap @@ -1 +1 @@ -374102 \ No newline at end of file +418079 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap index 279f7c39c..073466b99 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -324208 \ No newline at end of file +322963 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_withClose.snap b/.forge-snapshots/PositionManager_mint_withClose.snap index 305b76dd7..1843093c8 100644 --- a/.forge-snapshots/PositionManager_mint_withClose.snap +++ b/.forge-snapshots/PositionManager_mint_withClose.snap @@ -1 +1 @@ -375508 \ No newline at end of file +419485 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_withSettlePair.snap b/.forge-snapshots/PositionManager_mint_withSettlePair.snap index 835439d65..173e7f3ea 100644 --- a/.forge-snapshots/PositionManager_mint_withSettlePair.snap +++ b/.forge-snapshots/PositionManager_mint_withSettlePair.snap @@ -1 +1 @@ -374708 \ No newline at end of file +418685 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap index 8965e304a..75c74a425 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -419655 \ No newline at end of file +463653 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_subscribe.snap b/.forge-snapshots/PositionManager_subscribe.snap index 7172622fe..e4eada758 100644 --- a/.forge-snapshots/PositionManager_subscribe.snap +++ b/.forge-snapshots/PositionManager_subscribe.snap @@ -1 +1 @@ -88052 \ No newline at end of file +84348 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_unsubscribe.snap b/.forge-snapshots/PositionManager_unsubscribe.snap index 722233d86..0151c604d 100644 --- a/.forge-snapshots/PositionManager_unsubscribe.snap +++ b/.forge-snapshots/PositionManager_unsubscribe.snap @@ -1 +1 @@ -62411 \ No newline at end of file +59238 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap b/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap index 648659437..1623910a1 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap @@ -1 +1 @@ -115662 \ No newline at end of file +115511 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap b/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap index c735c47a3..e35171c53 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap @@ -1 +1 @@ -124477 \ No newline at end of file +124326 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap b/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap index 690cf4c57..1a1262d13 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap @@ -1 +1 @@ -130195 \ No newline at end of file +130044 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn2Hops.snap b/.forge-snapshots/V4Router_ExactIn2Hops.snap index 7796edbe1..a902b10ec 100644 --- a/.forge-snapshots/V4Router_ExactIn2Hops.snap +++ b/.forge-snapshots/V4Router_ExactIn2Hops.snap @@ -1 +1 @@ -179203 \ No newline at end of file +179052 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn3Hops.snap b/.forge-snapshots/V4Router_ExactIn3Hops.snap index 2ecc304bf..204d8770c 100644 --- a/.forge-snapshots/V4Router_ExactIn3Hops.snap +++ b/.forge-snapshots/V4Router_ExactIn3Hops.snap @@ -1 +1 @@ -228190 \ No newline at end of file +228039 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactInputSingle.snap b/.forge-snapshots/V4Router_ExactInputSingle.snap index 89920090c..78e17c574 100644 --- a/.forge-snapshots/V4Router_ExactInputSingle.snap +++ b/.forge-snapshots/V4Router_ExactInputSingle.snap @@ -1 +1 @@ -129465 \ No newline at end of file +129314 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap b/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap index ab8830dbc..72a2d4fca 100644 --- a/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap @@ -1 +1 @@ -114901 \ No newline at end of file +114750 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap b/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap index da6da4ca0..193c9cfdb 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap @@ -1 +1 @@ -116714 \ No newline at end of file +116563 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap b/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap index f78f106c4..20bdc814a 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap @@ -1 +1 @@ -125529 \ No newline at end of file +125378 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap b/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap index 4645416bf..a8df2a4a3 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap @@ -1 +1 @@ -129446 \ No newline at end of file +129295 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut2Hops.snap b/.forge-snapshots/V4Router_ExactOut2Hops.snap index 69edacf10..09421110f 100644 --- a/.forge-snapshots/V4Router_ExactOut2Hops.snap +++ b/.forge-snapshots/V4Router_ExactOut2Hops.snap @@ -1 +1 @@ -179274 \ No newline at end of file +179123 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops.snap b/.forge-snapshots/V4Router_ExactOut3Hops.snap index 920f4b7a1..288f098b7 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops.snap @@ -1 +1 @@ -229109 \ No newline at end of file +228958 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap b/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap index 403f04049..2444dfab2 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap @@ -1 +1 @@ -220318 \ No newline at end of file +220167 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle.snap b/.forge-snapshots/V4Router_ExactOutputSingle.snap index 1c160394e..180382ac1 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle.snap @@ -1 +1 @@ -128716 \ No newline at end of file +128565 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap b/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap index ff5267a5a..d3838df44 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap @@ -1 +1 @@ -116059 \ No newline at end of file +115908 \ No newline at end of file diff --git a/lib/v4-core b/lib/v4-core index 5a7990b12..9c94b1a8d 160000 --- a/lib/v4-core +++ b/lib/v4-core @@ -1 +1 @@ -Subproject commit 5a7990b127314af61998f37b6689a74f9c2db453 +Subproject commit 9c94b1a8ded5b5c09bee0ed9526d10065756b83d diff --git a/src/PositionManager.sol b/src/PositionManager.sol index b2ba38c12..52c019232 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -18,14 +18,13 @@ import {IPositionManager} from "./interfaces/IPositionManager.sol"; import {Multicall_v4} from "./base/Multicall_v4.sol"; import {PoolInitializer} from "./base/PoolInitializer.sol"; import {DeltaResolver} from "./base/DeltaResolver.sol"; -import {PositionConfig, PositionConfigLibrary} from "./libraries/PositionConfig.sol"; import {BaseActionsRouter} from "./base/BaseActionsRouter.sol"; import {Actions} from "./libraries/Actions.sol"; import {Notifier} from "./base/Notifier.sol"; import {CalldataDecoder} from "./libraries/CalldataDecoder.sol"; import {Permit2Forwarder} from "./base/Permit2Forwarder.sol"; import {SlippageCheck} from "./libraries/SlippageCheck.sol"; -import {PositionConfigId, PositionConfigIdLibrary} from "./libraries/PositionConfigId.sol"; +import {PositionInfo, PositionInfoLibrary} from "./libraries/PositionInfoLibrary.sol"; // 444444444 // 444444444444 444444 @@ -105,25 +104,20 @@ contract PositionManager is Permit2Forwarder { using PoolIdLibrary for PoolKey; - using PositionConfigLibrary for PositionConfig; using StateLibrary for IPoolManager; using TransientStateLibrary for IPoolManager; using SafeCast for uint256; using SafeCast for int256; using CalldataDecoder for bytes; using SlippageCheck for BalanceDelta; - using PositionConfigIdLibrary for PositionConfigId; + using PositionInfoLibrary for PositionInfo; /// @inheritdoc IPositionManager /// @dev The ID of the next token that will be minted. Skips 0 uint256 public nextTokenId = 1; - mapping(uint256 tokenId => PositionConfigId configId) internal positionConfigs; - - /// @notice an internal getter for PositionConfigId to be used by Notifier - function _positionConfigs(uint256 tokenId) internal view override returns (PositionConfigId storage) { - return positionConfigs[tokenId]; - } + mapping(uint256 tokenId => PositionInfo info) public positionInfo; + mapping(bytes25 poolId => PoolKey poolKey) public poolKeys; constructor(IPoolManager _poolManager, IAllowanceTransfer _permit2, uint256 _unsubscribeGasLimit) BaseActionsRouter(_poolManager) @@ -149,14 +143,6 @@ contract PositionManager is _; } - /// @notice Reverts if the hash of the config does not equal the saved hash - /// @param tokenId the unique identifier of the ERC721 token - /// @param config the PositionConfig to check against - modifier onlyValidConfig(uint256 tokenId, PositionConfig calldata config) override { - if (positionConfigs[tokenId].getConfigId() != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); - _; - } - /// @inheritdoc IPositionManager function modifyLiquidities(bytes calldata unlockData, uint256 deadline) external @@ -184,48 +170,33 @@ contract PositionManager is function _handleAction(uint256 action, bytes calldata params) internal virtual override { if (action < Actions.SETTLE) { if (action == Actions.INCREASE_LIQUIDITY) { - ( - uint256 tokenId, - PositionConfig calldata config, - uint256 liquidity, - uint128 amount0Max, - uint128 amount1Max, - bytes calldata hookData - ) = params.decodeModifyLiquidityParams(); - _increase(tokenId, config, liquidity, amount0Max, amount1Max, hookData); + (uint256 tokenId, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, bytes calldata hookData) = + params.decodeModifyLiquidityParams(); + _increase(tokenId, liquidity, amount0Max, amount1Max, hookData); return; } else if (action == Actions.DECREASE_LIQUIDITY) { - ( - uint256 tokenId, - PositionConfig calldata config, - uint256 liquidity, - uint128 amount0Min, - uint128 amount1Min, - bytes calldata hookData - ) = params.decodeModifyLiquidityParams(); - _decrease(tokenId, config, liquidity, amount0Min, amount1Min, hookData); + (uint256 tokenId, uint256 liquidity, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) = + params.decodeModifyLiquidityParams(); + _decrease(tokenId, liquidity, amount0Min, amount1Min, hookData); return; } else if (action == Actions.MINT_POSITION) { ( - PositionConfig calldata config, + PoolKey calldata poolKey, + int24 tickLower, + int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, address owner, bytes calldata hookData ) = params.decodeMintParams(); - _mint(config, liquidity, amount0Max, amount1Max, _mapRecipient(owner), hookData); + _mint(poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, _mapRecipient(owner), hookData); return; } else if (action == Actions.BURN_POSITION) { // Will automatically decrease liquidity to 0 if the position is not already empty. - ( - uint256 tokenId, - PositionConfig calldata config, - uint128 amount0Min, - uint128 amount1Min, - bytes calldata hookData - ) = params.decodeBurnParams(); - _burn(tokenId, config, amount0Min, amount1Min, hookData); + (uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) = + params.decodeBurnParams(); + _burn(tokenId, amount0Min, amount1Min, hookData); return; } } else { @@ -265,15 +236,16 @@ contract PositionManager is /// @dev Calling increase with 0 liquidity will credit the caller with any underlying fees of the position function _increase( uint256 tokenId, - PositionConfig calldata config, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, bytes calldata hookData - ) internal onlyIfApproved(msgSender(), tokenId) onlyValidConfig(tokenId, config) { + ) internal onlyIfApproved(msgSender(), tokenId) { + (PoolKey memory poolKey, PositionInfo info) = getPoolAndPositionInfo(tokenId); + // Note: The tokenId is used as the salt for this position, so every minted position has unique storage in the pool manager. (BalanceDelta liquidityDelta, BalanceDelta feesAccrued) = - _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); + _modifyLiquidity(info, poolKey, liquidity.toInt256(), bytes32(tokenId), hookData); // Slippage checks should be done on the principal liquidityDelta which is the liquidityDelta - feesAccrued (liquidityDelta - feesAccrued).validateMaxIn(amount0Max, amount1Max); } @@ -281,21 +253,24 @@ contract PositionManager is /// @dev Calling decrease with 0 liquidity will credit the caller with any underlying fees of the position function _decrease( uint256 tokenId, - PositionConfig calldata config, uint256 liquidity, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData - ) internal onlyIfApproved(msgSender(), tokenId) onlyValidConfig(tokenId, config) { + ) internal onlyIfApproved(msgSender(), tokenId) { + (PoolKey memory poolKey, PositionInfo info) = getPoolAndPositionInfo(tokenId); + // Note: the tokenId is used as the salt. (BalanceDelta liquidityDelta, BalanceDelta feesAccrued) = - _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); + _modifyLiquidity(info, poolKey, -(liquidity.toInt256()), bytes32(tokenId), hookData); // Slippage checks should be done on the principal liquidityDelta which is the liquidityDelta - feesAccrued (liquidityDelta - feesAccrued).validateMinOut(amount0Min, amount1Min); } function _mint( - PositionConfig calldata config, + PoolKey calldata poolKey, + int24 tickLower, + int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, @@ -310,39 +285,46 @@ contract PositionManager is } _mint(owner, tokenId); + // Initialize the position info + PositionInfo info = PositionInfoLibrary.initialize(poolKey, tickLower, tickUpper); + positionInfo[tokenId] = info; + + // Store the poolKey if it is not already stored. + // On UniswapV4, the minimum tick spacing is 1, which means that if the tick spacing is 0, the pool key has not been set. + bytes25 poolId = info.poolId(); + if (poolKeys[poolId].tickSpacing == 0) { + poolKeys[poolId] = poolKey; + } + // fee delta can be ignored as this is a new position - (BalanceDelta liquidityDelta,) = _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); + (BalanceDelta liquidityDelta,) = + _modifyLiquidity(info, poolKey, liquidity.toInt256(), bytes32(tokenId), hookData); liquidityDelta.validateMaxIn(amount0Max, amount1Max); - positionConfigs[tokenId].setConfigId(config.toId()); - - emit MintPosition(tokenId, config); } /// @dev this is overloaded with ERC721Permit_v4._burn - function _burn( - uint256 tokenId, - PositionConfig calldata config, - uint128 amount0Min, - uint128 amount1Min, - bytes calldata hookData - ) internal onlyIfApproved(msgSender(), tokenId) onlyValidConfig(tokenId, config) { - uint256 liquidity = getPositionLiquidity(tokenId, config); + function _burn(uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) + internal + onlyIfApproved(msgSender(), tokenId) + { + (PoolKey memory poolKey, PositionInfo info) = getPoolAndPositionInfo(tokenId); + + uint256 liquidity = uint256(_getLiquidity(tokenId, poolKey, info.tickLower(), info.tickUpper())); + + // Clear the position info. + positionInfo[tokenId] = PositionInfoLibrary.EMPTY_POSITION_INFO; + // Burn the token. + _burn(tokenId); // Can only call modify if there is non zero liquidity. if (liquidity > 0) { (BalanceDelta liquidityDelta, BalanceDelta feesAccrued) = - _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); + _modifyLiquidity(info, poolKey, -(liquidity.toInt256()), bytes32(tokenId), hookData); // Slippage checks should be done on the principal liquidityDelta which is the liquidityDelta - feesAccrued (liquidityDelta - feesAccrued).validateMinOut(amount0Min, amount1Min); } - bool hasSubscriber = positionConfigs[tokenId].hasSubscriber(); - - delete positionConfigs[tokenId]; - // Burn the token. - _burn(tokenId); - - if (hasSubscriber) _unsubscribe(tokenId, config); + if (info.hasSubscriber()) _unsubscribe(tokenId); } function _settlePair(Currency currency0, Currency currency1) internal { @@ -392,24 +374,25 @@ contract PositionManager is } function _modifyLiquidity( - PositionConfig calldata config, + PositionInfo info, + PoolKey memory poolKey, int256 liquidityChange, bytes32 salt, bytes calldata hookData ) internal returns (BalanceDelta liquidityDelta, BalanceDelta feesAccrued) { (liquidityDelta, feesAccrued) = poolManager.modifyLiquidity( - config.poolKey, + poolKey, IPoolManager.ModifyLiquidityParams({ - tickLower: config.tickLower, - tickUpper: config.tickUpper, + tickLower: info.tickLower(), + tickUpper: info.tickUpper(), liquidityDelta: liquidityChange, salt: salt }), hookData ); - if (positionConfigs[uint256(salt)].hasSubscriber()) { - _notifyModifyLiquidity(uint256(salt), config, liquidityChange, feesAccrued); + if (info.hasSubscriber()) { + _notifyModifyLiquidity(uint256(salt), liquidityChange, feesAccrued); } } @@ -423,25 +406,40 @@ contract PositionManager is } } + /// @notice an internal helper used by Notifier + function _setSubscribed(uint256 tokenId) internal override { + positionInfo[tokenId] = positionInfo[tokenId].setSubscribe(); + } + + /// @notice an internal helper used by Notifier + function _setUnsubscribed(uint256 tokenId) internal override { + positionInfo[tokenId] = positionInfo[tokenId].setUnsubscribe(); + } + /// @dev overrides solmate transferFrom in case a notification to subscribers is needed function transferFrom(address from, address to, uint256 id) public virtual override { super.transferFrom(from, to, id); - if (positionConfigs[id].hasSubscriber()) _notifyTransfer(id, from, to); + if (positionInfo[id].hasSubscriber()) _notifyTransfer(id, from, to); } /// @inheritdoc IPositionManager - function getPositionLiquidity(uint256 tokenId, PositionConfig calldata config) - public - view - returns (uint128 liquidity) - { - bytes32 positionId = - Position.calculatePositionKey(address(this), config.tickLower, config.tickUpper, bytes32(tokenId)); - liquidity = poolManager.getPositionLiquidity(config.poolKey.toId(), positionId); + function getPoolAndPositionInfo(uint256 tokenId) public view returns (PoolKey memory poolKey, PositionInfo info) { + info = positionInfo[tokenId]; + poolKey = poolKeys[info.poolId()]; } /// @inheritdoc IPositionManager - function getPositionConfigId(uint256 tokenId) external view returns (bytes32) { - return positionConfigs[tokenId].getConfigId(); + function getPositionLiquidity(uint256 tokenId) external view returns (uint128 liquidity) { + (PoolKey memory poolKey, PositionInfo info) = getPoolAndPositionInfo(tokenId); + liquidity = _getLiquidity(tokenId, poolKey, info.tickLower(), info.tickUpper()); + } + + function _getLiquidity(uint256 tokenId, PoolKey memory poolKey, int24 tickLower, int24 tickUpper) + internal + view + returns (uint128 liquidity) + { + bytes32 positionId = Position.calculatePositionKey(address(this), tickLower, tickUpper, bytes32(tokenId)); + liquidity = poolManager.getPositionLiquidity(poolKey.toId(), positionId); } } diff --git a/src/base/Notifier.sol b/src/base/Notifier.sol index bb94f73a7..558e85b7f 100644 --- a/src/base/Notifier.sol +++ b/src/base/Notifier.sol @@ -2,16 +2,14 @@ pragma solidity ^0.8.0; import {ISubscriber} from "../interfaces/ISubscriber.sol"; -import {PositionConfig} from "../libraries/PositionConfig.sol"; -import {PositionConfigId, PositionConfigIdLibrary} from "../libraries/PositionConfigId.sol"; import {INotifier} from "../interfaces/INotifier.sol"; import {CustomRevert} from "@uniswap/v4-core/src/libraries/CustomRevert.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; +import {PositionInfo} from "../libraries/PositionInfoLibrary.sol"; /// @notice Notifier is used to opt in to sending updates to external contracts about position modifications or transfers abstract contract Notifier is INotifier { using CustomRevert for bytes4; - using PositionConfigIdLibrary for PositionConfigId; ISubscriber private constant NO_SUBSCRIBER = ISubscriber(address(0)); @@ -31,29 +29,24 @@ abstract contract Notifier is INotifier { /// @param tokenId the tokenId of the position modifier onlyIfApproved(address caller, uint256 tokenId) virtual; - /// @notice Only allow callers that provide the correct config for the tokenId - /// @dev to be implemented by the parent contract (PositionManager) - /// @param tokenId the tokenId of the position - /// @param config the config of the tokenId - modifier onlyValidConfig(uint256 tokenId, PositionConfig calldata config) virtual; + function _setUnsubscribed(uint256 tokenId) internal virtual; - function _positionConfigs(uint256 tokenId) internal view virtual returns (PositionConfigId storage); + function _setSubscribed(uint256 tokenId) internal virtual; /// @inheritdoc INotifier - function subscribe(uint256 tokenId, PositionConfig calldata config, address newSubscriber, bytes calldata data) + function subscribe(uint256 tokenId, address newSubscriber, bytes calldata data) external payable onlyIfApproved(msg.sender, tokenId) - onlyValidConfig(tokenId, config) { - // will revert below if the user already has a subscriber - _positionConfigs(tokenId).setSubscribe(); ISubscriber _subscriber = subscriber[tokenId]; if (_subscriber != NO_SUBSCRIBER) revert AlreadySubscribed(tokenId, address(_subscriber)); + _setSubscribed(tokenId); + subscriber[tokenId] = ISubscriber(newSubscriber); - bool success = _call(newSubscriber, abi.encodeCall(ISubscriber.notifySubscribe, (tokenId, config, data))); + bool success = _call(newSubscriber, abi.encodeCall(ISubscriber.notifySubscribe, (tokenId, data))); if (!success) { Wrap__SubscriptionReverted.selector.bubbleUpAndRevertWith(newSubscriber); @@ -63,20 +56,16 @@ abstract contract Notifier is INotifier { } /// @inheritdoc INotifier - function unsubscribe(uint256 tokenId, PositionConfig calldata config) - external - payable - onlyIfApproved(msg.sender, tokenId) - onlyValidConfig(tokenId, config) - { - if (!_positionConfigs(tokenId).hasSubscriber()) NotSubscribed.selector.revertWith(); - _unsubscribe(tokenId, config); + function unsubscribe(uint256 tokenId) external payable onlyIfApproved(msg.sender, tokenId) { + _unsubscribe(tokenId); } - function _unsubscribe(uint256 tokenId, PositionConfig calldata config) internal { - _positionConfigs(tokenId).setUnsubscribe(); + function _unsubscribe(uint256 tokenId) internal { ISubscriber _subscriber = subscriber[tokenId]; + if (_subscriber == NO_SUBSCRIBER) revert NotSubscribed(); + _setUnsubscribed(tokenId); + delete subscriber[tokenId]; if (address(_subscriber).code.length > 0) { @@ -84,23 +73,18 @@ abstract contract Notifier is INotifier { // otherwise, users can select a gas limit where .notifyUnsubscribe hits OutOfGas yet the // transaction/unsubscription can still succeed if (gasleft() < unsubscribeGasLimit) GasLimitTooLow.selector.revertWith(); - try _subscriber.notifyUnsubscribe{gas: unsubscribeGasLimit}(tokenId, config) {} catch {} + try _subscriber.notifyUnsubscribe{gas: unsubscribeGasLimit}(tokenId) {} catch {} } emit Unsubscription(tokenId, address(_subscriber)); } - function _notifyModifyLiquidity( - uint256 tokenId, - PositionConfig memory config, - int256 liquidityChange, - BalanceDelta feesAccrued - ) internal { + function _notifyModifyLiquidity(uint256 tokenId, int256 liquidityChange, BalanceDelta feesAccrued) internal { ISubscriber _subscriber = subscriber[tokenId]; bool success = _call( address(_subscriber), - abi.encodeCall(ISubscriber.notifyModifyLiquidity, (tokenId, config, liquidityChange, feesAccrued)) + abi.encodeCall(ISubscriber.notifyModifyLiquidity, (tokenId, liquidityChange, feesAccrued)) ); if (!success) { @@ -125,9 +109,4 @@ abstract contract Notifier is INotifier { success := call(gas(), target, 0, add(encodedCall, 0x20), mload(encodedCall), 0, 0) } } - - /// @inheritdoc INotifier - function hasSubscriber(uint256 tokenId) external view returns (bool) { - return _positionConfigs(tokenId).hasSubscriber(); - } } diff --git a/src/interfaces/INotifier.sol b/src/interfaces/INotifier.sol index 17bb8f961..d6cca9083 100644 --- a/src/interfaces/INotifier.sol +++ b/src/interfaces/INotifier.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {PositionConfig} from "../libraries/PositionConfig.sol"; import {ISubscriber} from "./ISubscriber.sol"; /// @notice This interface is used to opt in to sending updates to external contracts about position modifications or transfers @@ -33,27 +32,18 @@ interface INotifier { /// @notice Enables the subscriber to receive notifications for a respective position /// @param tokenId the ERC721 tokenId - /// @param config the corresponding PositionConfig for the tokenId /// @param newSubscriber the address of the subscriber contract /// @param data caller-provided data that's forwarded to the subscriber contract /// @dev Calling subscribe when a position is already subscribed will revert /// @dev payable so it can be multicalled with NATIVE related actions - function subscribe(uint256 tokenId, PositionConfig calldata config, address newSubscriber, bytes calldata data) - external - payable; + function subscribe(uint256 tokenId, address newSubscriber, bytes calldata data) external payable; /// @notice Removes the subscriber from receiving notifications for a respective position /// @param tokenId the ERC721 tokenId - /// @param config the corresponding PositionConfig for the tokenId - /// @dev Callers must specify a high gas limit (remaining gas should be higher than subscriberGasLimit) such that the subscriber can be notified + /// @dev Callers must specify a high gas limit (remaining gas should be higher than unsubscriberGasLimit) such that the subscriber can be notified /// @dev payable so it can be multicalled with NATIVE related actions /// @dev Must always allow a user to unsubscribe. In the case of a malicious subscriber, a user can always unsubscribe safely, ensuring liquidity is always modifiable. - function unsubscribe(uint256 tokenId, PositionConfig calldata config) external payable; - - /// @notice Returns whether a position should call out to notify a subscribing contract on modification or transfer - /// @param tokenId the ERC721 tokenId - /// @return bool whether or not the position has a subscriber - function hasSubscriber(uint256 tokenId) external view returns (bool); + function unsubscribe(uint256 tokenId) external payable; /// @notice Returns and determines the maximum allowable gas-used for notifying unsubscribe /// @return uint256 the maximum gas limit when notifying a subscriber's `notifyUnsubscribe` function diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index ff0e03fde..616b51ccb 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {PositionConfig} from "../libraries/PositionConfig.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {PositionInfo} from "../libraries/PositionInfoLibrary.sol"; import {INotifier} from "./INotifier.sol"; @@ -12,11 +13,6 @@ interface IPositionManager is INotifier { error NotApproved(address caller); /// @notice Thrown when the block.timestamp exceeds the user-provided deadline error DeadlinePassed(uint256 deadline); - /// @notice Thrown when the caller provides the incorrect PositionConfig for a corresponding tokenId when modifying liquidity - error IncorrectPositionConfigForTokenId(uint256 tokenId); - - /// @notice Emitted when a new liquidity position is minted - event MintPosition(uint256 indexed tokenId, PositionConfig config); /// @notice Unlocks Uniswap v4 PoolManager and batches actions for modifying liquidity /// @dev This is the standard entrypoint for the PositionManager @@ -35,16 +31,12 @@ interface IPositionManager is INotifier { function nextTokenId() external view returns (uint256); /// @param tokenId the ERC721 tokenId - /// @return bytes32 a truncated hash of the position's poolkey, tickLower, and tickUpper - /// @dev truncates the least significant bit of the hash - function getPositionConfigId(uint256 tokenId) external view returns (bytes32); - - /// @param tokenId the ERC721 tokenId - /// @param config the corresponding PositionConfig for the tokenId /// @return liquidity the position's liquidity, as a liquidityAmount /// @dev this value can be processed as an amount0 and amount1 by using the LiquidityAmounts library - function getPositionLiquidity(uint256 tokenId, PositionConfig calldata config) - external - view - returns (uint128 liquidity); + function getPositionLiquidity(uint256 tokenId) external view returns (uint128 liquidity); + + /// @param tokenId the ERC721 tokenId + /// @return PositionInfo a uint256 packed value holding information about the position including the range (tickLower, tickUpper) + /// @return poolKey the pool key of the position + function getPoolAndPositionInfo(uint256 tokenId) external view returns (PoolKey memory, PositionInfo); } diff --git a/src/interfaces/ISubscriber.sol b/src/interfaces/ISubscriber.sol index a1393c7a9..1e6f04762 100644 --- a/src/interfaces/ISubscriber.sol +++ b/src/interfaces/ISubscriber.sol @@ -1,31 +1,22 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {PositionConfig} from "../libraries/PositionConfig.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; /// @notice Interface that a Subscriber contract should implement to receive updates from the v4 position manager interface ISubscriber { /// @param tokenId the token ID of the position - /// @param config details about the position /// @param data additional data passed in by the caller - function notifySubscribe(uint256 tokenId, PositionConfig memory config, bytes memory data) external; + function notifySubscribe(uint256 tokenId, bytes memory data) external; /// @notice Called when a position unsubscribes from the subscriber /// @dev This call's gas is capped at `unsubscribeGasLimit` (set at deployment) /// @dev Because of EIP-150, solidity may only allocate 63/64 of gasleft() /// @param tokenId the token ID of the position - /// @param config details about the position - function notifyUnsubscribe(uint256 tokenId, PositionConfig memory config) external; + function notifyUnsubscribe(uint256 tokenId) external; /// @param tokenId the token ID of the position - /// @param config details about the position /// @param liquidityChange the change in liquidity on the underlying position /// @param feesAccrued the fees to be collected from the position as a result of the modifyLiquidity call - function notifyModifyLiquidity( - uint256 tokenId, - PositionConfig memory config, - int256 liquidityChange, - BalanceDelta feesAccrued - ) external; + function notifyModifyLiquidity(uint256 tokenId, int256 liquidityChange, BalanceDelta feesAccrued) external; /// @param tokenId the token ID of the position /// @param previousOwner address of the old owner /// @param newOwner address of the new owner diff --git a/src/libraries/CalldataDecoder.sol b/src/libraries/CalldataDecoder.sol index a01cf0762..5bcad8dea 100644 --- a/src/libraries/CalldataDecoder.sol +++ b/src/libraries/CalldataDecoder.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; -import {PositionConfig} from "./PositionConfig.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {IV4Router} from "../interfaces/IV4Router.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; /// @title Library for abi decoding in calldata library CalldataDecoder { @@ -44,35 +44,30 @@ library CalldataDecoder { } } - /// @dev equivalent to: abi.decode(params, (uint256, PositionConfig, uint256, uint128, uint128, bytes)) in calldata + /// @dev equivalent to: abi.decode(params, (uint256, uint256, uint128, uint128, bytes)) in calldata function decodeModifyLiquidityParams(bytes calldata params) internal pure - returns ( - uint256 tokenId, - PositionConfig calldata config, - uint256 liquidity, - uint128 amount0, - uint128 amount1, - bytes calldata hookData - ) + returns (uint256 tokenId, uint256 liquidity, uint128 amount0, uint128 amount1, bytes calldata hookData) { assembly ("memory-safe") { tokenId := calldataload(params.offset) - config := add(params.offset, 0x20) - liquidity := calldataload(add(params.offset, 0x100)) - amount0 := calldataload(add(params.offset, 0x120)) - amount1 := calldataload(add(params.offset, 0x140)) + liquidity := calldataload(add(params.offset, 0x20)) + amount0 := calldataload(add(params.offset, 0x40)) + amount1 := calldataload(add(params.offset, 0x60)) } - hookData = params.toBytes(11); + + hookData = params.toBytes(4); } - /// @dev equivalent to: abi.decode(params, (PositionConfig, uint256, uint128, uint128, address, bytes)) in calldata + /// @dev equivalent to: abi.decode(params, (PoolKey, int24, int24, uint256, uint128, uint128, address, bytes)) in calldata function decodeMintParams(bytes calldata params) internal pure returns ( - PositionConfig calldata config, + PoolKey calldata poolKey, + int24 tickLower, + int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, @@ -81,7 +76,9 @@ library CalldataDecoder { ) { assembly ("memory-safe") { - config := params.offset + poolKey := params.offset + tickLower := calldataload(add(params.offset, 0xa0)) + tickUpper := calldataload(add(params.offset, 0xc0)) liquidity := calldataload(add(params.offset, 0xe0)) amount0Max := calldataload(add(params.offset, 0x100)) amount1Max := calldataload(add(params.offset, 0x120)) @@ -90,25 +87,19 @@ library CalldataDecoder { hookData = params.toBytes(11); } - /// @dev equivalent to: abi.decode(params, (uint256, PositionConfig, uint128, uint128, bytes)) in calldata + /// @dev equivalent to: abi.decode(params, (uint256, uint128, uint128, bytes)) in calldata function decodeBurnParams(bytes calldata params) internal pure - returns ( - uint256 tokenId, - PositionConfig calldata config, - uint128 amount0Min, - uint128 amount1Min, - bytes calldata hookData - ) + returns (uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) { assembly ("memory-safe") { tokenId := calldataload(params.offset) - config := add(params.offset, 0x20) - amount0Min := calldataload(add(params.offset, 0x100)) - amount1Min := calldataload(add(params.offset, 0x120)) + amount0Min := calldataload(add(params.offset, 0x20)) + amount1Min := calldataload(add(params.offset, 0x40)) } - hookData = params.toBytes(10); + + hookData = params.toBytes(3); } /// @dev equivalent to: abi.decode(params, (IV4Router.ExactInputParams)) diff --git a/src/libraries/PositionInfoLibrary.sol b/src/libraries/PositionInfoLibrary.sol new file mode 100644 index 000000000..981500559 --- /dev/null +++ b/src/libraries/PositionInfoLibrary.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; + +/** + * @dev PositionInfo is a packed version of solidity structure. + * Using the packaged version saves gas and memory by not storing the structure fields in memory slots. + * + * Layout: + * 200 bits poolId | 24 bits tickUpper | 24 bits tickLower | 8 bits hasSubscriber + * + * Fields in the direction from the least significant bit: + * + * A flag to know if the tokenId is subscribed to an address + * uint8 hasSubscriber; + * + * The tickUpper of the position + * int24 tickUpper; + * + * The tickLower of the position + * int24 tickLower; + * + * The truncated poolId. Truncates a bytes32 value so the most signifcant (highest) 200 bits are used. + * bytes25 poolId; + * + * Note: If more bits are needed, hasSubscriber can be a single bit. + * + */ +type PositionInfo is uint256; + +library PositionInfoLibrary { + using PoolIdLibrary for PoolKey; + + PositionInfo internal constant EMPTY_POSITION_INFO = PositionInfo.wrap(0); + + uint256 internal constant MASK_UPPER_200_BITS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000; + uint256 internal constant MASK_8_BITS = 0xFF; + uint24 internal constant MASK_24_BITS = 0xFFFFFF; + uint256 internal constant SET_UNSUBSCRIBE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00; + uint256 internal constant SET_SUBSCRIBE = 0x01; + uint8 internal constant TICK_LOWER_OFFSET = 8; + uint8 internal constant TICK_UPPER_OFFSET = 32; + + /// @dev This poolId is NOT compatible with the poolId used in UniswapV4 core. It is truncated to 25 bytes, and just used to lookup PoolKey in the poolKeys mapping. + function poolId(PositionInfo info) internal pure returns (bytes25 _poolId) { + assembly ("memory-safe") { + _poolId := and(MASK_UPPER_200_BITS, info) + } + } + + function tickLower(PositionInfo info) internal pure returns (int24 _tickLower) { + assembly ("memory-safe") { + _tickLower := signextend(2, shr(TICK_LOWER_OFFSET, info)) + } + } + + function tickUpper(PositionInfo info) internal pure returns (int24 _tickUpper) { + assembly ("memory-safe") { + _tickUpper := signextend(2, shr(TICK_UPPER_OFFSET, info)) + } + } + + function hasSubscriber(PositionInfo info) internal pure returns (bool _hasSubscriber) { + assembly ("memory-safe") { + _hasSubscriber := and(MASK_8_BITS, info) + } + } + + /// @dev this does not actually set any storage + function setSubscribe(PositionInfo info) internal pure returns (PositionInfo _info) { + assembly ("memory-safe") { + _info := or(info, SET_SUBSCRIBE) + } + } + + /// @dev this does not actually set any storage + function setUnsubscribe(PositionInfo info) internal pure returns (PositionInfo _info) { + assembly ("memory-safe") { + _info := and(info, SET_UNSUBSCRIBE) + } + } + + /// @notice Creates the default PositionInfo struct + /// @dev Called when minting a new position + /// @param _poolKey the pool key of the position + /// @param _tickLower the lower tick of the position + /// @param _tickUpper the upper tick of the position + /// @return info packed position info, with the truncated poolId and the hasSubscriber flag set to false + function initialize(PoolKey memory _poolKey, int24 _tickLower, int24 _tickUpper) + internal + pure + returns (PositionInfo info) + { + bytes25 _poolId = bytes25(PoolId.unwrap(_poolKey.toId())); + assembly { + info := + or( + or(and(MASK_UPPER_200_BITS, _poolId), shl(TICK_UPPER_OFFSET, and(MASK_24_BITS, _tickUpper))), + shl(TICK_LOWER_OFFSET, and(MASK_24_BITS, _tickLower)) + ) + } + } +} diff --git a/test/libraries/CalldataDecoder.t.sol b/test/libraries/CalldataDecoder.t.sol index 293986974..da24aa959 100644 --- a/test/libraries/CalldataDecoder.t.sol +++ b/test/libraries/CalldataDecoder.t.sol @@ -6,7 +6,7 @@ import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {MockCalldataDecoder} from "../mocks/MockCalldataDecoder.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {IV4Router} from "../../src/interfaces/IV4Router.sol"; import {PathKey} from "../../src/libraries/PathKey.sol"; @@ -19,44 +19,34 @@ contract CalldataDecoderTest is Test { function test_fuzz_decodeModifyLiquidityParams( uint256 _tokenId, - PositionConfig calldata _config, uint256 _liquidity, uint128 _amount0, uint128 _amount1, bytes calldata _hookData ) public view { - bytes memory params = abi.encode(_tokenId, _config, _liquidity, _amount0, _amount1, _hookData); - ( - uint256 tokenId, - PositionConfig memory config, - uint256 liquidity, - uint128 amount0, - uint128 amount1, - bytes memory hookData - ) = decoder.decodeModifyLiquidityParams(params); + bytes memory params = abi.encode(_tokenId, _liquidity, _amount0, _amount1, _hookData); + (uint256 tokenId, uint256 liquidity, uint128 amount0, uint128 amount1, bytes memory hookData) = + decoder.decodeModifyLiquidityParams(params); assertEq(tokenId, _tokenId); assertEq(liquidity, _liquidity); assertEq(amount0, _amount0); assertEq(amount1, _amount1); assertEq(hookData, _hookData); - _assertEq(_config, config); } function test_fuzz_decodeBurnParams( uint256 _tokenId, - PositionConfig calldata _config, uint128 _amount0Min, uint128 _amount1Min, bytes calldata _hookData ) public view { - bytes memory params = abi.encode(_tokenId, _config, _amount0Min, _amount1Min, _hookData); - (uint256 tokenId, PositionConfig memory config, uint128 amount0Min, uint128 amount1Min, bytes memory hookData) = + bytes memory params = abi.encode(_tokenId, _amount0Min, _amount1Min, _hookData); + (uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes memory hookData) = decoder.decodeBurnParams(params); assertEq(tokenId, _tokenId); assertEq(hookData, _hookData); - _assertEq(_config, config); assertEq(amount0Min, _amount0Min); assertEq(amount1Min, _amount1Min); } @@ -69,22 +59,27 @@ contract CalldataDecoderTest is Test { address _owner, bytes calldata _hookData ) public view { - bytes memory params = abi.encode(_config, _liquidity, _amount0Max, _amount1Max, _owner, _hookData); - ( - PositionConfig memory config, - uint256 liquidity, - uint128 amount0Max, - uint128 amount1Max, - address owner, - bytes memory hookData - ) = decoder.decodeMintParams(params); - - assertEq(liquidity, _liquidity); - assertEq(amount0Max, _amount0Max); - assertEq(amount1Max, _amount1Max); - assertEq(owner, _owner); - assertEq(hookData, _hookData); - _assertEq(_config, config); + bytes memory params = abi.encode( + _config.poolKey, + _config.tickLower, + _config.tickUpper, + _liquidity, + _amount0Max, + _amount1Max, + _owner, + _hookData + ); + + (MockCalldataDecoder.MintParams memory mintParams) = decoder.decodeMintParams(params); + + assertEq(mintParams.liquidity, _liquidity); + assertEq(mintParams.amount0Max, _amount0Max); + assertEq(mintParams.amount1Max, _amount1Max); + assertEq(mintParams.owner, _owner); + assertEq(mintParams.hookData, _hookData); + _assertEq(mintParams.poolKey, _config.poolKey); + assertEq(mintParams.tickLower, _config.tickLower); + assertEq(mintParams.tickUpper, _config.tickUpper); } function test_fuzz_decodeSwapExactInParams(IV4Router.ExactInputParams calldata _swapParams) public view { @@ -203,12 +198,6 @@ contract CalldataDecoderTest is Test { } } - function _assertEq(PositionConfig memory config1, PositionConfig memory config2) internal pure { - _assertEq(config1.poolKey, config2.poolKey); - assertEq(config1.tickLower, config2.tickLower); - assertEq(config1.tickUpper, config2.tickUpper); - } - function _assertEq(PoolKey memory key1, PoolKey memory key2) internal pure { assertEq(Currency.unwrap(key1.currency0), Currency.unwrap(key2.currency0)); assertEq(Currency.unwrap(key1.currency1), Currency.unwrap(key2.currency1)); diff --git a/test/libraries/PositionConfig.t.sol b/test/libraries/PositionConfig.t.sol deleted file mode 100644 index 187ee370e..000000000 --- a/test/libraries/PositionConfig.t.sol +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "forge-std/Test.sol"; - -import {PositionConfig, PositionConfigLibrary} from "../../src/libraries/PositionConfig.sol"; -import {PositionConfigId, PositionConfigIdLibrary} from "../../src/libraries/PositionConfigId.sol"; - -contract PositionConfigTest is Test { - using PositionConfigLibrary for PositionConfig; - using PositionConfigIdLibrary for PositionConfigId; - - mapping(uint256 => PositionConfigId) internal testConfigs; - - bytes32 public constant UPPER_BIT_SET = 0x8000000000000000000000000000000000000000000000000000000000000000; - - function test_fuzz_toId(PositionConfig calldata config) public pure { - bytes32 expectedId = _calculateExpectedId(config); - assertEq(expectedId, config.toId()); - } - - function test_fuzz_setConfigId(uint256 tokenId, PositionConfig calldata config) public { - testConfigs[tokenId].setConfigId(config.toId()); - - bytes32 expectedConfigId = _calculateExpectedId(config); - - bytes32 actualConfigId = testConfigs[tokenId].id; - assertEq(expectedConfigId, actualConfigId); - } - - function test_fuzz_getConfigId(uint256 tokenId, PositionConfig calldata config) public { - bytes32 expectedId = _calculateExpectedId(config); - // set - testConfigs[tokenId] = PositionConfigId({id: expectedId}); - - assertEq(expectedId, testConfigs[tokenId].getConfigId()); - } - - function test_fuzz_setConfigId_getConfigId(uint256 tokenId, PositionConfig calldata config) public { - testConfigs[tokenId].setConfigId(config.toId()); - - bytes32 expectedId = _calculateExpectedId(config); - - assertEq(testConfigs[tokenId].getConfigId(), testConfigs[tokenId].id); - assertEq(testConfigs[tokenId].getConfigId(), expectedId); - } - - function test_fuzz_getConfigId_equal_afterSubscribe(uint256 tokenId, PositionConfig calldata config) public { - testConfigs[tokenId].setConfigId(config.toId()); - testConfigs[tokenId].setSubscribe(); - - assertEq(testConfigs[tokenId].getConfigId(), config.toId()); - } - - function test_fuzz_setSubscribe(uint256 tokenId) public { - testConfigs[tokenId].setSubscribe(); - bytes32 upperBitSet = testConfigs[tokenId].id; - - assertEq(upperBitSet, UPPER_BIT_SET); - } - - function test_fuzz_setConfigId_setSubscribe(uint256 tokenId, PositionConfig calldata config) public { - testConfigs[tokenId].setConfigId(config.toId()); - testConfigs[tokenId].setSubscribe(); - - bytes32 expectedConfig = _calculateExpectedId(config) | UPPER_BIT_SET; - - bytes32 _config = testConfigs[tokenId].id; - - assertEq(_config, expectedConfig); - } - - function test_fuzz_setUnsubscribe(uint256 tokenId) public { - testConfigs[tokenId].setSubscribe(); - bytes32 _config = testConfigs[tokenId].id; - assertEq(_config, UPPER_BIT_SET); - testConfigs[tokenId].setUnsubscribe(); - _config = testConfigs[tokenId].id; - assertEq(_config, 0); - } - - function test_hasSubscriber(uint256 tokenId) public { - testConfigs[tokenId].setSubscribe(); - assert(testConfigs[tokenId].hasSubscriber()); - testConfigs[tokenId].setUnsubscribe(); - assert(!testConfigs[tokenId].hasSubscriber()); - } - - function test_fuzz_setConfigId_setSubscribe_setUnsubscribe_getConfigId( - uint256 tokenId, - PositionConfig calldata config - ) public { - assertEq(testConfigs[tokenId].getConfigId(), 0); - - testConfigs[tokenId].setConfigId(config.toId()); - assertEq(testConfigs[tokenId].getConfigId(), config.toId()); - - testConfigs[tokenId].setSubscribe(); - assertEq(testConfigs[tokenId].getConfigId(), config.toId()); - assertEq(testConfigs[tokenId].hasSubscriber(), true); - - testConfigs[tokenId].setUnsubscribe(); - assertEq(testConfigs[tokenId].getConfigId(), config.toId()); - assertEq(testConfigs[tokenId].hasSubscriber(), false); - } - - function test_fuzz_setSubscribe_twice(uint256 tokenId, PositionConfig calldata config) public { - assertFalse(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setSubscribe(); - testConfigs[tokenId].setSubscribe(); - assertTrue(testConfigs[tokenId].hasSubscriber()); - - // It is known behavior that setting the config id just stores the id directly, meaning the upper most bit is unset. - // This is ok because setConfigId will only ever be called on mint. - testConfigs[tokenId].setConfigId(config.toId()); - assertFalse(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setSubscribe(); - testConfigs[tokenId].setSubscribe(); - assertTrue(testConfigs[tokenId].hasSubscriber()); - } - - function test_fuzz_setUnsubscribe_twice(uint256 tokenId, PositionConfig calldata config) public { - assertFalse(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setUnsubscribe(); - testConfigs[tokenId].setUnsubscribe(); - assertFalse(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setConfigId(config.toId()); - assertFalse(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setUnsubscribe(); - testConfigs[tokenId].setUnsubscribe(); - assertFalse(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setSubscribe(); - assertTrue(testConfigs[tokenId].hasSubscriber()); - - testConfigs[tokenId].setUnsubscribe(); - testConfigs[tokenId].setUnsubscribe(); - assertFalse(testConfigs[tokenId].hasSubscriber()); - } - - function _calculateExpectedId(PositionConfig calldata config) internal pure returns (bytes32 expectedId) { - expectedId = keccak256( - abi.encodePacked( - config.poolKey.currency0, - config.poolKey.currency1, - config.poolKey.fee, - config.poolKey.tickSpacing, - config.poolKey.hooks, - config.tickLower, - config.tickUpper - ) - ); - // truncate the upper bit - expectedId = expectedId >> 1; - } -} diff --git a/test/libraries/PositionInfoLibrary.t.sol b/test/libraries/PositionInfoLibrary.t.sol new file mode 100644 index 000000000..12af50151 --- /dev/null +++ b/test/libraries/PositionInfoLibrary.t.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import "forge-std/Test.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {PositionInfo, PositionInfoLibrary, PoolId} from "../../src/libraries/PositionInfoLibrary.sol"; + +contract PositionInfoLibraryTest is Test { + using PositionInfoLibrary for PositionInfo; + using PoolIdLibrary for PoolKey; + + function setUp() public {} + + function test_fuzz_initialize(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) public pure { + PositionInfo info = PositionInfoLibrary.initialize(poolKey, tickLower, tickUpper); + + assertEq(info.poolId(), bytes25(PoolId.unwrap(poolKey.toId()))); + assertEq(info.tickLower(), tickLower); + assertEq(info.tickUpper(), tickUpper); + assertEq(info.hasSubscriber(), false); + } + + function test_fuzz_initialize_setSubscribed(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) public pure { + PositionInfo info = PositionInfoLibrary.initialize(poolKey, tickLower, tickUpper); + assertEq(info.hasSubscriber(), false); + info = info.setSubscribe(); + assertEq(info.hasSubscriber(), true); + assertEq(info.tickLower(), tickLower); + assertEq(info.tickUpper(), tickUpper); + assertEq(info.poolId(), bytes25(PoolId.unwrap(poolKey.toId()))); + } + + function test_fuzz_initialize_setUnsubscribed(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) + public + pure + { + PositionInfo info = PositionInfoLibrary.initialize(poolKey, tickLower, tickUpper); + assertEq(info.hasSubscriber(), false); + info = info.setSubscribe(); + assertEq(info.hasSubscriber(), true); + assertEq(info.tickLower(), tickLower); + assertEq(info.tickUpper(), tickUpper); + assertEq(info.poolId(), bytes25(PoolId.unwrap(poolKey.toId()))); + + info = info.setUnsubscribe(); + assertEq(info.hasSubscriber(), false); + assertEq(info.tickLower(), tickLower); + assertEq(info.tickUpper(), tickUpper); + assertEq(info.poolId(), bytes25(PoolId.unwrap(poolKey.toId()))); + } + + function test_fuzz_setSubscribe(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) public pure { + PositionInfo info = PositionInfoLibrary.initialize(poolKey, tickLower, tickUpper); + assertEq(info.hasSubscriber(), false); + info = info.setSubscribe(); + assertEq(info.hasSubscriber(), true); + + // Calling set subscribe again does nothing. + info = info.setSubscribe(); + assertEq(info.hasSubscriber(), true); + } + + function test_fuzz_setUnsubscribe(PoolKey memory poolKey, int24 tickLower, int24 tickUpper) public pure { + PositionInfo info = PositionInfoLibrary.initialize(poolKey, tickLower, tickUpper); + assertEq(info.hasSubscriber(), false); + info = info.setSubscribe(); + assertEq(info.hasSubscriber(), true); + info = info.setUnsubscribe(); + assertEq(info.hasSubscriber(), false); + + // Calling set unsubscribe again does nothing. + info = info.setUnsubscribe(); + assertEq(info.hasSubscriber(), false); + } +} diff --git a/test/mocks/MockBadSubscribers.sol b/test/mocks/MockBadSubscribers.sol index b5fd64f40..28f151823 100644 --- a/test/mocks/MockBadSubscribers.sol +++ b/test/mocks/MockBadSubscribers.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.20; import {ISubscriber} from "../../src/interfaces/ISubscriber.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; @@ -30,11 +29,11 @@ contract MockReturnDataSubscriber is ISubscriber { _; } - function notifySubscribe(uint256, PositionConfig memory, bytes memory) external onlyByPosm { + function notifySubscribe(uint256, bytes memory) external onlyByPosm { notifySubscribeCount++; } - function notifyUnsubscribe(uint256, PositionConfig memory) external onlyByPosm { + function notifyUnsubscribe(uint256) external onlyByPosm { notifyUnsubscribeCount++; uint256 _memPtr = memPtr; assembly { @@ -45,7 +44,7 @@ contract MockReturnDataSubscriber is ISubscriber { } } - function notifyModifyLiquidity(uint256, PositionConfig memory, int256, BalanceDelta) external onlyByPosm { + function notifyModifyLiquidity(uint256, int256, BalanceDelta) external onlyByPosm { notifyModifyLiquidityCount++; } @@ -77,17 +76,17 @@ contract MockRevertSubscriber is ISubscriber { _; } - function notifySubscribe(uint256, PositionConfig memory, bytes memory) external view onlyByPosm { + function notifySubscribe(uint256, bytes memory) external view onlyByPosm { if (shouldRevert) { revert TestRevert("notifySubscribe"); } } - function notifyUnsubscribe(uint256, PositionConfig memory) external view onlyByPosm { + function notifyUnsubscribe(uint256) external view onlyByPosm { revert TestRevert("notifyUnsubscribe"); } - function notifyModifyLiquidity(uint256, PositionConfig memory, int256, BalanceDelta) external view onlyByPosm { + function notifyModifyLiquidity(uint256, int256, BalanceDelta) external view onlyByPosm { revert TestRevert("notifyModifyLiquidity"); } diff --git a/test/mocks/MockCalldataDecoder.sol b/test/mocks/MockCalldataDecoder.sol index 695a526b2..d5edbb64b 100644 --- a/test/mocks/MockCalldataDecoder.sol +++ b/test/mocks/MockCalldataDecoder.sol @@ -1,26 +1,31 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {CalldataDecoder} from "../../src/libraries/CalldataDecoder.sol"; import {IV4Router} from "../../src/interfaces/IV4Router.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; // we need to use a mock contract to make the calls happen in calldata not memory contract MockCalldataDecoder { using CalldataDecoder for bytes; + // This is used to avoid compiling with via-ir. + struct MintParams { + PoolKey poolKey; + int24 tickLower; + int24 tickUpper; + uint256 liquidity; + uint128 amount0Max; + uint128 amount1Max; + address owner; + bytes hookData; + } + function decodeModifyLiquidityParams(bytes calldata params) external pure - returns ( - uint256 tokenId, - PositionConfig calldata config, - uint256 liquidity, - uint128 amount0, - uint128 amount1, - bytes calldata hookData - ) + returns (uint256 tokenId, uint256 liquidity, uint128 amount0, uint128 amount1, bytes calldata hookData) { return params.decodeModifyLiquidityParams(); } @@ -28,13 +33,7 @@ contract MockCalldataDecoder { function decodeBurnParams(bytes calldata params) external pure - returns ( - uint256 tokenId, - PositionConfig calldata config, - uint128 amount0Min, - uint128 amount1Min, - bytes calldata hookData - ) + returns (uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) { return params.decodeBurnParams(); } @@ -71,19 +70,27 @@ contract MockCalldataDecoder { return params.decodeSwapExactOutSingleParams(); } - function decodeMintParams(bytes calldata params) - external - pure - returns ( - PositionConfig calldata config, + function decodeMintParams(bytes calldata params) external pure returns (MintParams memory mintParams) { + ( + PoolKey memory poolKey, + int24 tickLower, + int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, address owner, - bytes calldata hookData - ) - { - return params.decodeMintParams(); + bytes memory hookData + ) = params.decodeMintParams(); + return MintParams({ + poolKey: poolKey, + tickLower: tickLower, + tickUpper: tickUpper, + liquidity: liquidity, + amount0Max: amount0Max, + amount1Max: amount1Max, + owner: owner, + hookData: hookData + }); } function decodeCurrencyAndAddress(bytes calldata params) diff --git a/test/mocks/MockSubscriber.sol b/test/mocks/MockSubscriber.sol index 83ea2e39c..1e1fda151 100644 --- a/test/mocks/MockSubscriber.sol +++ b/test/mocks/MockSubscriber.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.20; import {ISubscriber} from "../../src/interfaces/ISubscriber.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; @@ -32,19 +31,16 @@ contract MockSubscriber is ISubscriber { _; } - function notifySubscribe(uint256, PositionConfig memory, bytes memory data) external onlyByPosm { + function notifySubscribe(uint256, bytes memory data) external onlyByPosm { notifySubscribeCount++; subscribeData = data; } - function notifyUnsubscribe(uint256, PositionConfig memory) external onlyByPosm { + function notifyUnsubscribe(uint256) external onlyByPosm { notifyUnsubscribeCount++; } - function notifyModifyLiquidity(uint256, PositionConfig memory, int256 _liquidityChange, BalanceDelta _feesAccrued) - external - onlyByPosm - { + function notifyModifyLiquidity(uint256, int256 _liquidityChange, BalanceDelta _feesAccrued) external onlyByPosm { notifyModifyLiquidityCount++; liquidityChange = _liquidityChange; feesAccrued = _feesAccrued; diff --git a/test/position-managers/Execute.t.sol b/test/position-managers/Execute.t.sol index 5417c71a1..42fb1a7b6 100644 --- a/test/position-managers/Execute.t.sol +++ b/test/position-managers/Execute.t.sol @@ -19,7 +19,7 @@ import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {PositionManager} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {ActionConstants} from "../../src/libraries/ActionConstants.sol"; import {Actions} from "../../src/libraries/Actions.sol"; @@ -72,7 +72,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { increaseLiquidity(tokenId, config, liquidityToAdd, ZERO_BYTES); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, initialLiquidity + liquidityToAdd); } @@ -92,17 +92,17 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd2, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd2, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); lpm.modifyLiquidities(calls, _deadline); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, initialLiquidity + liquidityToAdd + liquidityToAdd2); } @@ -122,17 +122,17 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd2, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd2, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithSettlePair(config.poolKey); lpm.modifyLiquidities(calls, _deadline); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, initialLiquidity + liquidityToAdd + liquidityToAdd2); } @@ -149,7 +149,9 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { planner.add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, initialLiquidity, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -159,13 +161,13 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { ); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); lpm.modifyLiquidities(calls, _deadline); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, initialLiquidity + liquidityToAdd); } @@ -197,14 +199,14 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.BURN_POSITION, - abi.encode( - tokenId, config, uint128(-delta.amount0()) - 1 wei, uint128(-delta.amount1()) - 1 wei, ZERO_BYTES - ) + abi.encode(tokenId, uint128(-delta.amount0()) - 1 wei, uint128(-delta.amount1()) - 1 wei, ZERO_BYTES) ); planner.add( Actions.MINT_POSITION, abi.encode( - newConfig, + newConfig.poolKey, + newConfig.tickLower, + newConfig.tickUpper, newLiquidity, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -234,7 +236,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { { // old position has no liquidity - uint128 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint128 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); // new token was minted @@ -243,7 +245,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { // new token has expected liquidity - liquidity = lpm.getPositionLiquidity(newTokenId, newConfig); + liquidity = lpm.getPositionLiquidity(newTokenId); assertEq(liquidity, newLiquidity); } } diff --git a/test/position-managers/FeeCollection.t.sol b/test/position-managers/FeeCollection.t.sol index 54ad44ad3..837e2a82d 100644 --- a/test/position-managers/FeeCollection.t.sol +++ b/test/position-managers/FeeCollection.t.sol @@ -14,7 +14,7 @@ import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {PositionManager} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index f4d103e11..ba0ec2f88 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -21,7 +21,7 @@ import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {DeltaResolver} from "../../src/base/DeltaResolver.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {SlippageCheck} from "../../src/libraries/SlippageCheck.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {Actions} from "../../src/libraries/Actions.sol"; @@ -122,12 +122,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { planner.add( Actions.INCREASE_LIQUIDITY, abi.encode( - tokenIdAlice, - config, - liquidityDelta, - feesOwedAlice.amount0() / 2, - feesOwedAlice.amount1() / 2, - ZERO_BYTES + tokenIdAlice, liquidityDelta, feesOwedAlice.amount0() / 2, feesOwedAlice.amount1() / 2, ZERO_BYTES ) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(alice)); @@ -189,9 +184,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode( - tokenIdAlice, config, liquidityDelta, feesOwedAlice.amount0(), feesOwedAlice.amount1(), ZERO_BYTES - ) + abi.encode(tokenIdAlice, liquidityDelta, feesOwedAlice.amount0(), feesOwedAlice.amount1(), ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); vm.startPrank(alice); @@ -248,7 +241,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenIdAlice, config, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenIdAlice, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency0, 18 wei)); // alice is willing to forfeit 18 wei planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency1, 18 wei)); @@ -351,7 +344,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenIdAlice, config, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenIdAlice, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency0, 1 wei)); // alice is willing to forfeit 1 wei planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency1, 1 wei)); @@ -627,7 +620,16 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.MINT_POSITION, - abi.encode(config, liquidityAlice, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, alice, ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + liquidityAlice, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + alice, + ZERO_BYTES + ) ); planner.add(Actions.SETTLE, abi.encode(currency0, ActionConstants.OPEN_DELTA, false)); planner.add(Actions.SETTLE, abi.encode(currency1, ActionConstants.OPEN_DELTA, false)); @@ -669,7 +671,16 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.MINT_POSITION, - abi.encode(config, liquidityAlice, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, alice, ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + liquidityAlice, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + alice, + ZERO_BYTES + ) ); planner.add(Actions.SETTLE, abi.encode(currency0, ActionConstants.OPEN_DELTA, false)); planner.add(Actions.SETTLE, abi.encode(currency1, ActionConstants.OPEN_DELTA, false)); @@ -707,14 +718,14 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { mint(config, liquidityAlice, alice, ZERO_BYTES); uint256 tokenIdAlice = lpm.nextTokenId() - 1; - uint256 liquidity = lpm.getPositionLiquidity(tokenIdAlice, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenIdAlice); assertEq(liquidity, liquidityAlice); // alice increases with the balance in the position manager Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenIdAlice, config, liquidityAlice, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenIdAlice, liquidityAlice, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.SETTLE, abi.encode(currency0, ActionConstants.OPEN_DELTA, false)); planner.add(Actions.SETTLE, abi.encode(currency1, ActionConstants.OPEN_DELTA, false)); @@ -742,7 +753,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { uint256 amount0 = uint128(-delta.amount0()); uint256 amount1 = uint128(-delta.amount1()); - liquidity = lpm.getPositionLiquidity(tokenIdAlice, config); + liquidity = lpm.getPositionLiquidity(tokenIdAlice); assertEq(liquidity, 2 * liquidityAlice); // The balances were swept back to this address. @@ -779,7 +790,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency0, maxClear)); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency1, maxClear)); @@ -808,7 +819,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency0, type(uint256).max)); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency1, type(uint256).max)); diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index 475965d56..fcad290cd 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -32,12 +32,11 @@ import {MockSubscriber} from "../mocks/MockSubscriber.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; import {Planner, Plan} from "../shared/Planner.sol"; -import {PositionConfig, PositionConfigLibrary} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; - using PositionConfigLibrary for PositionConfig; using Planner for Plan; using PoolIdLibrary for PoolKey; using StateLibrary for IPoolManager; @@ -91,7 +90,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); assertEq(balance0Before - currency0.balanceOfSelf(), uint256(int256(-delta.amount0())), "incorrect amount0"); @@ -117,7 +116,9 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { planner.add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -143,7 +144,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { lpm.modifyLiquidities{value: amount0 * 2 + 1}(calls, _deadline); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); // only paid the delta amount, with excess tokens returned to caller @@ -169,7 +170,16 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.MINT_POSITION, - abi.encode(config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + liquidityToAdd, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES + ) ); planner.add(Actions.SETTLE_PAIR, abi.encode(nativeKey.currency0, nativeKey.currency1)); // sweep the excess eth @@ -188,7 +198,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { lpm.modifyLiquidities{value: amount0 * 2 + 1}(calls, _deadline); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); // only paid the delta amount, with excess tokens returned to caller @@ -212,7 +222,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, config, liquidityToAdd, ActionConstants.MSG_SENDER, ZERO_BYTES); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); // burn liquidity @@ -227,7 +237,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length. assertEq(numDeltas, hook.numberDeltasReturned()); - liquidity = lpm.getPositionLiquidity(tokenId, config); + liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); // TODO: slightly off by 1 bip (0.0001%) @@ -265,7 +275,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, config, liquidityToAdd, ActionConstants.MSG_SENDER, ZERO_BYTES); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); // burn liquidity @@ -278,14 +288,14 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 numDeltas = hook.numberDeltasReturned(); Plan memory planner = Planner.init(); planner.add( - Actions.BURN_POSITION, abi.encode(tokenId, config, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); lpm.modifyLiquidities(calls, _deadline); // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length. assertEq(numDeltas, hook.numberDeltasReturned()); - liquidity = lpm.getPositionLiquidity(tokenId, config); + liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); // TODO: slightly off by 1 bip (0.0001%) @@ -323,7 +333,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, config, liquidityToAdd, ActionConstants.MSG_SENDER, ZERO_BYTES); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); // burn liquidity @@ -333,7 +343,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { burn(tokenId, config, ZERO_BYTES); BalanceDelta deltaBurn = getLastDelta(); - liquidity = lpm.getPositionLiquidity(tokenId, config); + liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); // TODO: slightly off by 1 bip (0.0001%) @@ -371,7 +381,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, config, liquidityToAdd, ActionConstants.MSG_SENDER, ZERO_BYTES); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); // burn liquidity @@ -380,13 +390,13 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( - Actions.BURN_POSITION, abi.encode(tokenId, config, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); lpm.modifyLiquidities(calls, _deadline); BalanceDelta deltaBurn = getLastDelta(); - liquidity = lpm.getPositionLiquidity(tokenId, config); + liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); // TODO: slightly off by 1 bip (0.0001%) @@ -437,7 +447,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { BalanceDelta delta = getLastDelta(); // verify position liquidity increased - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, liquidityToAdd + liquidityToAdd); // liquidity was doubled // verify native token balances changed as expected @@ -477,7 +487,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency0)); planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency1)); @@ -489,7 +499,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { BalanceDelta delta = getLastDelta(); // verify position liquidity increased - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, liquidityToAdd + liquidityToAdd); // liquidity was doubled // verify native token balances changed as expected, with overpaid tokens returned @@ -528,7 +538,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.SETTLE_PAIR, abi.encode(nativeKey.currency0, nativeKey.currency1)); // sweep the excess eth @@ -539,7 +549,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { BalanceDelta delta = getLastDelta(); // verify position liquidity increased - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, liquidityToAdd + liquidityToAdd); // liquidity was doubled // verify native token balances changed as expected, with overpaid tokens returned @@ -576,7 +586,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta); // verify native token balances changed as expected @@ -613,15 +623,13 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.DECREASE_LIQUIDITY, - abi.encode( - tokenId, config, decreaseLiquidityDelta, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES - ) + abi.encode(tokenId, decreaseLiquidityDelta, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); lpm.modifyLiquidities(calls, _deadline); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta); // verify native token balances changed as expected @@ -676,8 +684,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); Plan memory planner = Planner.init(); planner.add( - Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); lpm.modifyLiquidities(calls, _deadline); @@ -711,8 +718,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( - Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); address alice = address(0xABCD); @@ -755,8 +761,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( - Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, ActionConstants.MSG_SENDER); @@ -777,7 +782,16 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory plan = Planner.init(); plan.add( Actions.MINT_POSITION, - abi.encode(config, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + 100e18, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES + ) ); plan.add(Actions.CLOSE_CURRENCY, abi.encode(config.poolKey.currency0)); plan.add(Actions.CLOSE_CURRENCY, abi.encode(config.poolKey.currency1)); @@ -787,11 +801,11 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { bytes[] memory calls = new bytes[](2); calls[0] = abi.encodeWithSelector(lpm.modifyLiquidities.selector, actions, _deadline); - calls[1] = abi.encodeWithSelector(lpm.subscribe.selector, tokenId, config, sub, ZERO_BYTES); + calls[1] = abi.encodeWithSelector(lpm.subscribe.selector, tokenId, sub, ZERO_BYTES); lpm.multicall{value: 10e18}(calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 100e18); assertEq(sub.notifySubscribeCount(), 1); diff --git a/test/position-managers/Permit.t.sol b/test/position-managers/Permit.t.sol index 2219e3f07..ea3a9c6d9 100644 --- a/test/position-managers/Permit.t.sol +++ b/test/position-managers/Permit.t.sol @@ -17,7 +17,7 @@ import {IERC721Permit_v4} from "../../src/interfaces/IERC721Permit_v4.sol"; import {ERC721Permit_v4} from "../../src/base/ERC721Permit_v4.sol"; import {UnorderedNonce} from "../../src/base/UnorderedNonce.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; @@ -88,7 +88,7 @@ contract PermitTest is Test, PosmTestSetup { vm.stopPrank(); // alice's position increased liquidity - uint256 liquidity = lpm.getPositionLiquidity(tokenIdAlice, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenIdAlice); assertEq(liquidity, liquidityAlice + liquidityToAdd); } @@ -109,7 +109,7 @@ contract PermitTest is Test, PosmTestSetup { vm.stopPrank(); // alice's position decreased liquidity - uint256 liquidity = lpm.getPositionLiquidity(tokenIdAlice, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenIdAlice); assertEq(liquidity, liquidityAlice - liquidityToRemove); } @@ -262,7 +262,7 @@ contract PermitTest is Test, PosmTestSetup { decreaseLiquidity(tokenId, config, liquidityToRemove, ZERO_BYTES); vm.stopPrank(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, liquidityAlice - liquidityToRemove); } @@ -291,7 +291,7 @@ contract PermitTest is Test, PosmTestSetup { decreaseLiquidity(tokenId, config, liquidityToRemove, ZERO_BYTES); vm.stopPrank(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, liquidityAlice - liquidityToRemove); } diff --git a/test/position-managers/PositionManager.gas.t.sol b/test/position-managers/PositionManager.gas.t.sol index 2d4aff130..0fd658ead 100644 --- a/test/position-managers/PositionManager.gas.t.sol +++ b/test/position-managers/PositionManager.gas.t.sol @@ -19,7 +19,7 @@ import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {Actions} from "../../src/libraries/Actions.sol"; import {PositionManager} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {IMulticall_v4} from "../../src/interfaces/IMulticall_v4.sol"; import {Planner, Plan} from "../shared/Planner.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; @@ -79,7 +79,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -95,7 +97,16 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { function test_gas_mint_withSettlePair() public { Plan memory planner = Planner.init().add( Actions.MINT_POSITION, - abi.encode(config, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + 10_000 ether, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES + ) ); bytes memory calls = planner.finalizeModifyLiquidityWithSettlePair(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -112,7 +123,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -136,7 +149,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -160,7 +175,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -180,7 +197,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -194,7 +211,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithSettlePair(config.poolKey); @@ -238,7 +255,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenIdAlice, config, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenIdAlice, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); // because its a perfect autocompound, the delta is exactly 0 and we dont need to "close" deltas bytes memory calls = planner.encode(); @@ -286,7 +303,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init(); planner.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenIdAlice, config, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenIdAlice, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency0, halfTokensOwedAlice + 1 wei)); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(config.poolKey.currency1, halfTokensOwedAlice + 1 wei)); @@ -333,7 +350,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenIdAlice, config, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenIdAlice, liquidityDelta, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -349,7 +366,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -363,7 +380,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); @@ -388,7 +405,14 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { planner.add( Actions.MINT_POSITION, abi.encode( - config, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ActionConstants.MSG_SENDER, ZERO_BYTES + config.poolKey, + config.tickLower, + config.tickUpper, + 100e18, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + ActionConstants.MSG_SENDER, + ZERO_BYTES ) ); bytes memory actions = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -408,8 +432,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { // Collect by calling decrease with 0. Plan memory planner = Planner.init().add( - Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -426,8 +449,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { // Collect by calling decrease with 0. Plan memory planner = Planner.init().add( - Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); @@ -442,7 +464,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode( - config, + config.poolKey, + config.tickLower, + config.tickUpper, 10_001 ether, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -467,7 +491,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -488,8 +512,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { donateRouter.donate(config.poolKey, 0.2e18, 0.2e18, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -502,7 +525,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, ActionConstants.MSG_SENDER, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.BURN_POSITION, abi.encode(tokenId, config, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -515,7 +538,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, ActionConstants.MSG_SENDER, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.BURN_POSITION, abi.encode(tokenId, config, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(config.poolKey, address(this)); @@ -529,7 +552,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { decreaseLiquidity(tokenId, config, 10_000 ether, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.BURN_POSITION, abi.encode(tokenId, config, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); // There is no need to include CLOSE commands. @@ -546,10 +569,10 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); planner.add( - Actions.BURN_POSITION, abi.encode(tokenId, config, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); // We must include CLOSE commands. @@ -584,7 +607,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { planner.add( Actions.MINT_POSITION, abi.encode( - configNative, + configNative.poolKey, + configNative.tickLower, + configNative.tickUpper, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, @@ -615,7 +640,14 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { planner.add( Actions.MINT_POSITION, abi.encode( - configNative, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES + configNative.poolKey, + configNative.tickLower, + configNative.tickUpper, + liquidityToAdd, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES ) ); planner.add(Actions.SETTLE_PAIR, abi.encode(nativeKey.currency0, nativeKey.currency1)); @@ -676,8 +708,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, ActionConstants.MSG_SENDER, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.BURN_POSITION, - abi.encode(tokenId, configNative, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithClose(configNative.poolKey); @@ -690,8 +721,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, ActionConstants.MSG_SENDER, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.BURN_POSITION, - abi.encode(tokenId, configNative, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = planner.finalizeModifyLiquidityWithTakePair(configNative.poolKey, address(this)); @@ -705,8 +735,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { decreaseLiquidity(tokenId, configNative, 10_000 ether, ZERO_BYTES); Plan memory planner = Planner.init().add( - Actions.BURN_POSITION, - abi.encode(tokenId, configNative, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + Actions.BURN_POSITION, abi.encode(tokenId, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); // There is no need to include CLOSE commands. @@ -723,9 +752,9 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, configNative, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 10_000 ether, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); - planner.add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, 0 wei, 0 wei, ZERO_BYTES)); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, 0 wei, 0 wei, ZERO_BYTES)); // We must include CLOSE commands. bytes memory calls = planner.finalizeModifyLiquidityWithClose(configNative.poolKey); @@ -823,7 +852,16 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init(); planner.add( Actions.MINT_POSITION, - abi.encode(config, liquidityAlice, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, alice, ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + liquidityAlice, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + alice, + ZERO_BYTES + ) ); planner.add(Actions.SETTLE, abi.encode(currency0, ActionConstants.OPEN_DELTA, false)); planner.add(Actions.SETTLE, abi.encode(currency1, ActionConstants.OPEN_DELTA, false)); @@ -848,7 +886,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory plan = Planner.init(); plan.add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = plan.finalizeModifyLiquidityWithTake(config.poolKey, ActionConstants.MSG_SENDER); @@ -860,10 +898,10 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mint(config, 1e18, ActionConstants.MSG_SENDER, ZERO_BYTES); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); snapLastCall("PositionManager_subscribe"); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); snapLastCall("PositionManager_unsubscribe"); } } diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index 33a8fff7c..9b135e4f3 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -18,7 +18,7 @@ import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {ReentrancyLock} from "../../src/base/ReentrancyLock.sol"; import {Actions} from "../../src/libraries/Actions.sol"; import {PositionManager} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {Planner, Plan} from "../shared/Planner.sol"; @@ -71,13 +71,13 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF swap(key, true, -1e18, calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); // original liquidity unchanged assertEq(liquidity, initialLiquidity); // hook minted its own position - liquidity = lpm.getPositionLiquidity(hookTokenId, config); + liquidity = lpm.getPositionLiquidity(hookTokenId); assertEq(liquidity, newLiquidity); assertEq(lpm.ownerOf(tokenId), address(this)); // original position owned by this contract @@ -99,7 +99,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF swap(key, true, -1e18, calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, initialLiquidity + newLiquidity); } @@ -119,7 +119,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF swap(key, true, -1e18, calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, initialLiquidity - liquidityToDecrease); } @@ -145,7 +145,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF bytes memory calls = getCollectEncoded(tokenId, config, ZERO_BYTES); swap(key, true, -1e18, calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); // liquidity unchanged assertEq(liquidity, initialLiquidity); @@ -178,7 +178,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF bytes memory calls = getBurnEncoded(tokenId, config, ZERO_BYTES); swap(key, true, -1e18, calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); // liquidity burned assertEq(liquidity, 0); diff --git a/test/position-managers/PositionManager.multicall.t.sol b/test/position-managers/PositionManager.multicall.t.sol index 767c10be5..e5347fb43 100644 --- a/test/position-managers/PositionManager.multicall.t.sol +++ b/test/position-managers/PositionManager.multicall.t.sol @@ -21,7 +21,7 @@ import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {PoolInitializer} from "../../src/base/PoolInitializer.sol"; import {Actions} from "../../src/libraries/Actions.sol"; import {PositionManager} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {IMulticall_v4} from "../../src/interfaces/IMulticall_v4.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {Planner, Plan} from "../shared/Planner.sol"; @@ -110,7 +110,14 @@ contract PositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTest planner.add( Actions.MINT_POSITION, abi.encode( - config, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ActionConstants.MSG_SENDER, ZERO_BYTES + config.poolKey, + config.tickLower, + config.tickUpper, + 100e18, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + ActionConstants.MSG_SENDER, + ZERO_BYTES ) ); bytes memory actions = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -179,7 +186,7 @@ contract PositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTest Plan memory planner = Planner.init(); planner.add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 100e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 100e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory actions = planner.finalizeModifyLiquidityWithClose(config.poolKey); @@ -208,7 +215,7 @@ contract PositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTest Plan memory planner = Planner.init(); planner.add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 100e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 100e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory actions = planner.encode(); @@ -266,7 +273,7 @@ contract PositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTest vm.prank(bob); lpm.multicall(calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, liquidityAlice - liquidityToRemove); } @@ -307,7 +314,7 @@ contract PositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTest vm.prank(bob); lpm.multicall(calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); (_amount,,) = permit2.allowance(address(bob), Currency.unwrap(currency0), address(lpm)); @@ -363,7 +370,7 @@ contract PositionManagerMulticallTest is Test, Permit2SignatureHelpers, PosmTest vm.prank(bob); lpm.multicall(calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); (_amount0,,) = permit2.allowance(address(bob), Currency.unwrap(currency0), address(lpm)); (_amount1,,) = permit2.allowance(address(bob), Currency.unwrap(currency1), address(lpm)); diff --git a/test/position-managers/PositionManager.notifier.t.sol b/test/position-managers/PositionManager.notifier.t.sol index d06ed52d5..5e61891bd 100644 --- a/test/position-managers/PositionManager.notifier.t.sol +++ b/test/position-managers/PositionManager.notifier.t.sol @@ -8,22 +8,24 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol"; +import {BalanceDelta, toBalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; import {MockSubscriber} from "../mocks/MockSubscriber.sol"; import {ISubscriber} from "../../src/interfaces/ISubscriber.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {Plan, Planner} from "../shared/Planner.sol"; import {Actions} from "../../src/libraries/Actions.sol"; import {INotifier} from "../../src/interfaces/INotifier.sol"; import {MockReturnDataSubscriber, MockRevertSubscriber} from "../mocks/MockBadSubscribers.sol"; -import {BalanceDelta, toBalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; +import {PositionInfoLibrary, PositionInfo} from "../../src/libraries/PositionInfoLibrary.sol"; contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { using PoolIdLibrary for PoolKey; using StateLibrary for IPoolManager; using Planner for Plan; + using PositionInfoLibrary for PositionInfo; MockSubscriber sub; MockReturnDataSubscriber badSubscriber; @@ -53,7 +55,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { function test_subscribe_revertsWithEmptyPositionConfig() public { uint256 tokenId = lpm.nextTokenId(); vm.expectRevert("NOT_MINTED"); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); } function test_subscribe_revertsWhenNotApproved() public { @@ -63,22 +65,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { // this contract is not approved to operate on alice's liq vm.expectRevert(abi.encodeWithSelector(IPositionManager.NotApproved.selector, address(this))); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); - } - - function test_subscribe_reverts_withIncorrectConfig() public { - uint256 tokenId = lpm.nextTokenId(); - mint(config, 100e18, alice, ZERO_BYTES); - - // approve this contract to operate on alices liq - vm.startPrank(alice); - lpm.approve(address(this), tokenId); - vm.stopPrank(); - - PositionConfig memory incorrectConfig = PositionConfig({poolKey: key, tickLower: -300, tickUpper: 301}); - - vm.expectRevert(abi.encodeWithSelector(IPositionManager.IncorrectPositionConfigForTokenId.selector, tokenId)); - lpm.subscribe(tokenId, incorrectConfig, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); } function test_subscribe_succeeds() public { @@ -90,9 +77,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); assertEq(sub.notifySubscribeCount(), 1); } @@ -110,7 +97,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { vm.stopPrank(); vm.expectRevert(INotifier.NoCodeSubscriber.selector); - lpm.subscribe(tokenId, config, _subscriber, ZERO_BYTES); + lpm.subscribe(tokenId, _subscriber, ZERO_BYTES); } function test_subscribe_revertsWithAlreadySubscribed() public { @@ -123,13 +110,13 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { vm.stopPrank(); // successfully subscribe - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); assertEq(sub.notifySubscribeCount(), 1); vm.expectRevert(abi.encodeWithSelector(INotifier.AlreadySubscribed.selector, tokenId, sub)); - lpm.subscribe(tokenId, config, address(2), ZERO_BYTES); + lpm.subscribe(tokenId, address(2), ZERO_BYTES); } function test_notifyModifyLiquidity_succeeds() public { @@ -141,16 +128,16 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, 10e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, 10e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); } @@ -170,9 +157,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); // simulate selfdestruct by etching the bytecode to 0 @@ -197,9 +184,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); uint256 liquidityToAdd = 10e18; @@ -220,9 +207,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); lpm.transferFrom(alice, bob, tokenId); @@ -239,8 +226,8 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); // simulate selfdestruct by etching the bytecode to 0 @@ -259,9 +246,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); lpm.safeTransferFrom(alice, bob, tokenId); @@ -278,8 +265,8 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); // simulate selfdestruct by etching the bytecode to 0 @@ -298,9 +285,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); lpm.safeTransferFrom(alice, bob, tokenId, ""); @@ -317,12 +304,12 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); assertEq(sub.notifyUnsubscribeCount(), 1); - assertEq(lpm.hasSubscriber(tokenId), false); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), false); assertEq(address(lpm.subscriber(tokenId)), address(0)); } @@ -335,14 +322,14 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(badSubscriber), ZERO_BYTES); + lpm.subscribe(tokenId, address(badSubscriber), ZERO_BYTES); MockReturnDataSubscriber(badSubscriber).setReturnDataSize(0x600000); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); // the subscriber contract call failed bc it used too much gas assertEq(MockReturnDataSubscriber(badSubscriber).notifyUnsubscribeCount(), 0); - assertEq(lpm.hasSubscriber(tokenId), false); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), false); assertEq(address(lpm.subscriber(tokenId)), address(0)); } @@ -355,14 +342,14 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); // simulate selfdestruct by etching the bytecode to 0 vm.etch(address(sub), ZERO_BYTES); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); - assertEq(lpm.hasSubscriber(tokenId), false); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), false); assertEq(address(lpm.subscriber(tokenId)), address(0)); } @@ -372,23 +359,32 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { Plan memory plan = Planner.init(); plan.add( Actions.MINT_POSITION, - abi.encode(config, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + 100e18, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES + ) ); bytes memory actions = plan.finalizeModifyLiquidityWithSettlePair(config.poolKey); bytes[] memory calls = new bytes[](2); calls[0] = abi.encodeWithSelector(lpm.modifyLiquidities.selector, actions, _deadline); - calls[1] = abi.encodeWithSelector(lpm.subscribe.selector, tokenId, config, sub, ZERO_BYTES); + calls[1] = abi.encodeWithSelector(lpm.subscribe.selector, tokenId, sub, ZERO_BYTES); lpm.multicall(calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 100e18); assertEq(sub.notifySubscribeCount(), 1); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); } @@ -399,7 +395,16 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { Plan memory plan = Planner.init(); plan.add( Actions.MINT_POSITION, - abi.encode(config, 100e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + 100e18, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES + ) ); bytes memory actions = plan.finalizeModifyLiquidityWithSettlePair(config.poolKey); @@ -407,24 +412,24 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { plan = Planner.init(); plan.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, 10e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, 10e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); bytes memory actions2 = plan.finalizeModifyLiquidityWithSettlePair(config.poolKey); bytes[] memory calls = new bytes[](3); calls[0] = abi.encodeWithSelector(lpm.modifyLiquidities.selector, actions, _deadline); - calls[1] = abi.encodeWithSelector(lpm.subscribe.selector, tokenId, config, sub, ZERO_BYTES); + calls[1] = abi.encodeWithSelector(lpm.subscribe.selector, tokenId, sub, ZERO_BYTES); calls[2] = abi.encodeWithSelector(lpm.modifyLiquidities.selector, actions2, _deadline); lpm.multicall(calls); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 110e18); assertEq(sub.notifySubscribeCount(), 1); assertEq(sub.notifyModifyLiquidityCount(), 1); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); } @@ -438,7 +443,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { vm.stopPrank(); vm.expectRevert(INotifier.NotSubscribed.selector); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); } function test_unsubscribe_twice_reverts() public { @@ -450,12 +455,12 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); vm.expectRevert(INotifier.NotSubscribed.selector); - lpm.unsubscribe(tokenId, config); + lpm.unsubscribe(tokenId); } function test_subscribe_withData() public { @@ -469,9 +474,9 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), subData); + lpm.subscribe(tokenId, address(sub), subData); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(address(lpm.subscriber(tokenId)), address(sub)); assertEq(sub.notifySubscribeCount(), 1); assertEq(abi.decode(sub.subscribeData(), (address)), address(this)); @@ -495,7 +500,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { abi.encodeWithSelector(MockRevertSubscriber.TestRevert.selector, "notifySubscribe") ) ); - lpm.subscribe(tokenId, config, address(revertSubscriber), ZERO_BYTES); + lpm.subscribe(tokenId, address(revertSubscriber), ZERO_BYTES); } function test_notifyModifyLiquidiy_wraps_revert() public { @@ -507,13 +512,13 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(revertSubscriber), ZERO_BYTES); + lpm.subscribe(tokenId, address(revertSubscriber), ZERO_BYTES); Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add( Actions.INCREASE_LIQUIDITY, - abi.encode(tokenId, config, 10e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) + abi.encode(tokenId, 10e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ZERO_BYTES) ); } @@ -537,7 +542,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(revertSubscriber), ZERO_BYTES); + lpm.subscribe(tokenId, address(revertSubscriber), ZERO_BYTES); vm.expectRevert( abi.encodeWithSelector( @@ -558,7 +563,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(revertSubscriber), ZERO_BYTES); + lpm.subscribe(tokenId, address(revertSubscriber), ZERO_BYTES); vm.expectRevert( abi.encodeWithSelector( @@ -579,7 +584,7 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(revertSubscriber), ZERO_BYTES); + lpm.subscribe(tokenId, address(revertSubscriber), ZERO_BYTES); vm.expectRevert( abi.encodeWithSelector( @@ -603,16 +608,16 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), subData); + lpm.subscribe(tokenId, address(sub), subData); - assertEq(lpm.hasSubscriber(tokenId), true); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), true); assertEq(sub.notifyUnsubscribeCount(), 0); // burn the position, causing an unsubscribe burn(tokenId, config, ZERO_BYTES); // position is now unsubscribed - assertEq(lpm.hasSubscriber(tokenId), false); + assertEq(lpm.positionInfo(tokenId).hasSubscriber(), false); assertEq(sub.notifyUnsubscribeCount(), 1); } @@ -629,16 +634,16 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot { lpm.approve(address(this), tokenId); vm.stopPrank(); - lpm.subscribe(tokenId, config, address(sub), ZERO_BYTES); + lpm.subscribe(tokenId, address(sub), ZERO_BYTES); uint256 beforeUnsubCount = sub.notifyUnsubscribeCount(); if (gasLimit < lpm.unsubscribeGasLimit()) { // gas too low to call a valid unsubscribe vm.expectRevert(INotifier.GasLimitTooLow.selector); - lpm.unsubscribe{gas: gasLimit}(tokenId, config); + lpm.unsubscribe{gas: gasLimit}(tokenId); } else { // increasing gas limit succeeds and unsubscribe was called - lpm.unsubscribe{gas: gasLimit}(tokenId, config); + lpm.unsubscribe{gas: gasLimit}(tokenId); assertEq(sub.notifyUnsubscribeCount(), beforeUnsubCount + 1); } } diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index 7e7ea43f0..c0c0b96dd 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -24,7 +24,7 @@ import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {Actions} from "../../src/libraries/Actions.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {DeltaResolver} from "../../src/base/DeltaResolver.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; import {SlippageCheck} from "../../src/libraries/SlippageCheck.sol"; import {BaseActionsRouter} from "../../src/base/BaseActionsRouter.sol"; import {ActionConstants} from "../../src/libraries/ActionConstants.sol"; @@ -125,7 +125,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { assertEq(lpm.nextTokenId(), 2); assertEq(lpm.ownerOf(tokenId), address(this)); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); assertEq(balance0Before - currency0.balanceOfSelf(), uint256(int256(-delta.amount0())), "incorrect amount0"); @@ -239,7 +239,16 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.MINT_POSITION, - abi.encode(config, liquidityToAdd, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, address(this), ZERO_BYTES) + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + liquidityToAdd, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + address(this), + ZERO_BYTES + ) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(key.currency0, type(uint256).max)); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(key.currency1, type(uint256).max)); @@ -347,7 +356,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { assertEq(tokenId, 1); assertEq(lpm.ownerOf(1), address(this)); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); @@ -362,7 +371,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { burn(tokenId, config, ZERO_BYTES); assertEq(numDeltas, hook.numberDeltasReturned()); - liquidity = lpm.getPositionLiquidity(tokenId, config); + liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); @@ -391,7 +400,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { assertEq(tokenId, 1); assertEq(lpm.ownerOf(1), address(this)); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta)); @@ -413,7 +422,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { assertEq(uint256(int256(deltaBurn.amount0())), amount0); assertEq(uint256(int256(deltaBurn.amount1())), amount1); - liquidity = lpm.getPositionLiquidity(tokenId, config); + liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, 0); @@ -511,7 +520,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta); assertEq(currency0.balanceOfSelf(), balance0Before + uint256(uint128(delta.amount0()))); @@ -527,9 +536,6 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { (tokenId, params) = addFuzzyLiquidity(lpm, address(this), key, params, SQRT_PRICE_1_1, ZERO_BYTES); decreaseLiquidityDelta = uint256(bound(int256(decreaseLiquidityDelta), 0, params.liquidityDelta)); - PositionConfig memory config = - PositionConfig({poolKey: key, tickLower: params.tickLower, tickUpper: params.tickUpper}); - uint256 balance0Before = currency0.balanceOfSelf(); uint256 balance1Before = currency1.balanceOfSelf(); @@ -537,9 +543,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.DECREASE_LIQUIDITY, - abi.encode( - tokenId, config, decreaseLiquidityDelta, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES - ) + abi.encode(tokenId, decreaseLiquidityDelta, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(key.currency0, type(uint256).max)); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(key.currency1, type(uint256).max)); @@ -547,7 +551,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { lpm.modifyLiquidities(calls, _deadline); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta); // did not recieve tokens, as they were forfeited with CLEAR @@ -581,7 +585,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, liquidityToRemove, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, liquidityToRemove, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(key.currency0, amount0 - 1 wei)); planner.add(Actions.CLEAR_OR_TAKE, abi.encode(key.currency1, amount1 - 1 wei)); @@ -622,7 +626,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta); @@ -728,7 +732,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); BalanceDelta delta = getLastDelta(); - uint256 liquidity = lpm.getPositionLiquidity(tokenId, config); + uint256 liquidity = lpm.getPositionLiquidity(tokenId); assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta); @@ -813,7 +817,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { vm.stopPrank(); // position liquidity increased - uint256 newLiq = lpm.getPositionLiquidity(tokenId, config); + uint256 newLiq = lpm.getPositionLiquidity(tokenId); assertEq(newLiq, liquidity + liquidityToAdd); // alice paid the tokens @@ -855,7 +859,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { { // position liquidity decreased - uint256 newLiq = lpm.getPositionLiquidity(tokenId, config); + uint256 newLiq = lpm.getPositionLiquidity(tokenId); assertEq(newLiq, liquidity - liquidityToRemove); } @@ -915,7 +919,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory plan = Planner.init(); plan.add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); bytes memory calls = plan.finalizeModifyLiquidityWithTake(config.poolKey, ActionConstants.MSG_SENDER); @@ -947,12 +951,19 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory plan = Planner.init(); plan.add( Actions.DECREASE_LIQUIDITY, - abi.encode(tokenId, config, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) + abi.encode(tokenId, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES) ); plan.add( Actions.MINT_POSITION, abi.encode( - configMint, 1e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, ActionConstants.MSG_SENDER, ZERO_BYTES + configMint.poolKey, + configMint.tickLower, + configMint.tickUpper, + 1e18, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + ActionConstants.MSG_SENDER, + ZERO_BYTES ) ); plan.add(Actions.TAKE, abi.encode(key.currency0, ActionConstants.MSG_SENDER, ActionConstants.OPEN_DELTA)); @@ -973,14 +984,5 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { assertLt(uint256(int256(deltaDecrease.amount1())), uint256(int256(-deltaMint.amount1()))); // amount1 in the second position was greater than amount1 in the first position } - function test_mint_emits_event() public { - PositionConfig memory config = PositionConfig({poolKey: key, tickLower: -60, tickUpper: 60}); - uint256 tokenId = lpm.nextTokenId(); - - vm.expectEmit(true, false, false, true, address(lpm)); - emit IPositionManager.MintPosition(tokenId, config); - mint(config, 1e18, ActionConstants.MSG_SENDER, ZERO_BYTES); - } - function test_mint_slippageRevert() public {} } diff --git a/test/shared/FeeMath.sol b/test/shared/FeeMath.sol index 25bdba5f4..72ad5659a 100644 --- a/test/shared/FeeMath.sol +++ b/test/shared/FeeMath.sol @@ -13,7 +13,7 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {PositionManager} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "../shared/PositionConfig.sol"; library FeeMath { using SafeCast for uint256; diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index 65ed085d6..80d2d81e7 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -10,7 +10,7 @@ import {LiquidityAmounts} from "@uniswap/v4-core/test/utils/LiquidityAmounts.sol import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; import {PositionManager, Actions} from "../../src/PositionManager.sol"; -import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {PositionConfig} from "./PositionConfig.sol"; import {Planner, Plan} from "../shared/Planner.sol"; import {HookSavesDelta} from "./HookSavesDelta.sol"; @@ -99,7 +99,19 @@ abstract contract LiquidityOperations is CommonBase { bytes memory hookData ) internal pure returns (bytes memory) { Plan memory planner = Planner.init(); - planner.add(Actions.MINT_POSITION, abi.encode(config, liquidity, amount0Max, amount1Max, recipient, hookData)); + planner.add( + Actions.MINT_POSITION, + abi.encode( + config.poolKey, + config.tickLower, + config.tickUpper, + liquidity, + amount0Max, + amount1Max, + recipient, + hookData + ) + ); return planner.finalizeModifyLiquidityWithClose(config.poolKey); } @@ -124,9 +136,7 @@ abstract contract LiquidityOperations is CommonBase { bytes memory hookData ) internal pure returns (bytes memory) { Plan memory planner = Planner.init(); - planner.add( - Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, amount0Max, amount1Max, hookData) - ); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, liquidityToAdd, amount0Max, amount1Max, hookData)); return planner.finalizeModifyLiquidityWithClose(config.poolKey); } @@ -151,7 +161,7 @@ abstract contract LiquidityOperations is CommonBase { ) internal pure returns (bytes memory) { Plan memory planner = Planner.init(); planner.add( - Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToRemove, amount0Min, amount1Min, hookData) + Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, liquidityToRemove, amount0Min, amount1Min, hookData) ); return planner.finalizeModifyLiquidityWithClose(config.poolKey); } @@ -172,7 +182,7 @@ abstract contract LiquidityOperations is CommonBase { bytes memory hookData ) internal pure returns (bytes memory) { Plan memory planner = Planner.init(); - planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, amount0Min, amount1Min, hookData)); + planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, 0, amount0Min, amount1Min, hookData)); return planner.finalizeModifyLiquidityWithClose(config.poolKey); } @@ -192,7 +202,7 @@ abstract contract LiquidityOperations is CommonBase { bytes memory hookData ) internal pure returns (bytes memory) { Plan memory planner = Planner.init(); - planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, amount0Min, amount1Min, hookData)); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, amount0Min, amount1Min, hookData)); // Close needed on burn in case there is liquidity left in the position. return planner.finalizeModifyLiquidityWithClose(config.poolKey); } diff --git a/test/shared/PositionConfig.sol b/test/shared/PositionConfig.sol new file mode 100644 index 000000000..a2ab832bd --- /dev/null +++ b/test/shared/PositionConfig.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.24; + +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; + +// A helper struct used for tests +struct PositionConfig { + PoolKey poolKey; + int24 tickLower; + int24 tickUpper; +} diff --git a/test/shared/fuzz/LiquidityFuzzers.sol b/test/shared/fuzz/LiquidityFuzzers.sol index 02d6583f4..62f3f87bf 100644 --- a/test/shared/fuzz/LiquidityFuzzers.sol +++ b/test/shared/fuzz/LiquidityFuzzers.sol @@ -9,12 +9,13 @@ import {Fuzzers} from "@uniswap/v4-core/src/test/Fuzzers.sol"; import {IPositionManager} from "../../../src/interfaces/IPositionManager.sol"; import {Actions} from "../../../src/libraries/Actions.sol"; -import {PositionConfig} from "../../../src/libraries/PositionConfig.sol"; import {Planner, Plan} from "../../shared/Planner.sol"; contract LiquidityFuzzers is Fuzzers { using Planner for Plan; + uint128 constant _MAX_SLIPPAGE_INCREASE = type(uint128).max; + function addFuzzyLiquidity( IPositionManager lpm, address recipient, @@ -24,24 +25,23 @@ contract LiquidityFuzzers is Fuzzers { bytes memory hookData ) internal returns (uint256, IPoolManager.ModifyLiquidityParams memory) { params = Fuzzers.createFuzzyLiquidityParams(key, params, sqrtPriceX96); - PositionConfig memory config = - PositionConfig({poolKey: key, tickLower: params.tickLower, tickUpper: params.tickUpper}); - uint128 MAX_SLIPPAGE_INCREASE = type(uint128).max; Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode( - config, + key, + params.tickLower, + params.tickUpper, uint256(params.liquidityDelta), - MAX_SLIPPAGE_INCREASE, - MAX_SLIPPAGE_INCREASE, + _MAX_SLIPPAGE_INCREASE, + _MAX_SLIPPAGE_INCREASE, recipient, hookData ) ); uint256 tokenId = lpm.nextTokenId(); - bytes memory calls = planner.finalizeModifyLiquidityWithClose(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidityWithClose(key); lpm.modifyLiquidities(calls, block.timestamp + 1); return (tokenId, params);