From 8b1e6039490466feb1cdfee65b06d63840989a50 Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Thu, 9 Jan 2025 17:27:39 -0500 Subject: [PATCH 01/14] position descriptor proxy tests --- snapshots/PosMGasTest.json | 2 +- snapshots/PositionDescriptorTest.json | 2 +- test/PositionDescriptor.t.sol | 60 +++++++++---------- .../PositionManager.modifyLiquidities.t.sol | 4 +- test/shared/Deploy.sol | 13 ++++ test/shared/PosmTestSetup.sol | 8 ++- 6 files changed, 54 insertions(+), 35 deletions(-) diff --git a/snapshots/PosMGasTest.json b/snapshots/PosMGasTest.json index fab212ff..cc70748e 100644 --- a/snapshots/PosMGasTest.json +++ b/snapshots/PosMGasTest.json @@ -34,7 +34,7 @@ "PositionManager_mint_withSettlePair": "420939", "PositionManager_multicall_initialize_mint": "458237", "PositionManager_permit": "79175", - "PositionManager_permit_secondPosition": "62063", + "PositionManager_permit_secondPosition": "62075", "PositionManager_permit_twice": "44975", "PositionManager_subscribe": "87968", "PositionManager_unsubscribe": "62697", diff --git a/snapshots/PositionDescriptorTest.json b/snapshots/PositionDescriptorTest.json index df2ff3df..45898923 100644 --- a/snapshots/PositionDescriptorTest.json +++ b/snapshots/PositionDescriptorTest.json @@ -1,4 +1,4 @@ { "position descriptor initcode hash (without constructor params, as uint256)": "88482580191959945449130293370700011665153263709859488839371600440410373093991", - "positionDescriptor bytecode size": "24110" + "positionDescriptor bytecode size": "1488" } \ No newline at end of file diff --git a/test/PositionDescriptor.t.sol b/test/PositionDescriptor.t.sol index b215306b..6d62e7dd 100644 --- a/test/PositionDescriptor.t.sol +++ b/test/PositionDescriptor.t.sol @@ -48,46 +48,46 @@ contract PositionDescriptorTest is Test, PosmTestSetup { } function test_bytecodeSize_positionDescriptor() public { - vm.snapshotValue("positionDescriptor bytecode size", address(positionDescriptor).code.length); + vm.snapshotValue("positionDescriptor bytecode size", address(proxyAsImplementation).code.length); } function test_setup_succeeds() public view { - assertEq(address(positionDescriptor.poolManager()), address(manager)); - assertEq(positionDescriptor.wrappedNative(), WETH9); - assertEq(positionDescriptor.nativeCurrencyLabel(), nativeCurrencyLabel); + assertEq(address(proxyAsImplementation.poolManager()), address(manager)); + assertEq(proxyAsImplementation.wrappedNative(), WETH9); + assertEq(proxyAsImplementation.nativeCurrencyLabel(), nativeCurrencyLabel); } function test_currencyRatioPriority_mainnet_succeeds() public { vm.chainId(1); - assertEq(positionDescriptor.currencyRatioPriority(WETH9), CurrencyRatioSortOrder.DENOMINATOR); - assertEq(positionDescriptor.currencyRatioPriority(address(0)), CurrencyRatioSortOrder.DENOMINATOR); - assertEq(positionDescriptor.currencyRatioPriority(USDC), CurrencyRatioSortOrder.NUMERATOR_MOST); - assertEq(positionDescriptor.currencyRatioPriority(USDT), CurrencyRatioSortOrder.NUMERATOR_MORE); - assertEq(positionDescriptor.currencyRatioPriority(DAI), CurrencyRatioSortOrder.NUMERATOR); - assertEq(positionDescriptor.currencyRatioPriority(TBTC), CurrencyRatioSortOrder.DENOMINATOR_MORE); - assertEq(positionDescriptor.currencyRatioPriority(WBTC), CurrencyRatioSortOrder.DENOMINATOR_MOST); - assertEq(positionDescriptor.currencyRatioPriority(makeAddr("ALICE")), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(WETH9), CurrencyRatioSortOrder.DENOMINATOR); + assertEq(proxyAsImplementation.currencyRatioPriority(address(0)), CurrencyRatioSortOrder.DENOMINATOR); + assertEq(proxyAsImplementation.currencyRatioPriority(USDC), CurrencyRatioSortOrder.NUMERATOR_MOST); + assertEq(proxyAsImplementation.currencyRatioPriority(USDT), CurrencyRatioSortOrder.NUMERATOR_MORE); + assertEq(proxyAsImplementation.currencyRatioPriority(DAI), CurrencyRatioSortOrder.NUMERATOR); + assertEq(proxyAsImplementation.currencyRatioPriority(TBTC), CurrencyRatioSortOrder.DENOMINATOR_MORE); + assertEq(proxyAsImplementation.currencyRatioPriority(WBTC), CurrencyRatioSortOrder.DENOMINATOR_MOST); + assertEq(proxyAsImplementation.currencyRatioPriority(makeAddr("ALICE")), 0); } function test_currencyRatioPriority_notMainnet_succeeds() public { - assertEq(positionDescriptor.currencyRatioPriority(WETH9), CurrencyRatioSortOrder.DENOMINATOR); - assertEq(positionDescriptor.currencyRatioPriority(address(0)), CurrencyRatioSortOrder.DENOMINATOR); - assertEq(positionDescriptor.currencyRatioPriority(USDC), 0); - assertEq(positionDescriptor.currencyRatioPriority(USDT), 0); - assertEq(positionDescriptor.currencyRatioPriority(DAI), 0); - assertEq(positionDescriptor.currencyRatioPriority(TBTC), 0); - assertEq(positionDescriptor.currencyRatioPriority(WBTC), 0); - assertEq(positionDescriptor.currencyRatioPriority(makeAddr("ALICE")), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(WETH9), CurrencyRatioSortOrder.DENOMINATOR); + assertEq(proxyAsImplementation.currencyRatioPriority(address(0)), CurrencyRatioSortOrder.DENOMINATOR); + assertEq(proxyAsImplementation.currencyRatioPriority(USDC), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(USDT), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(DAI), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(TBTC), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(WBTC), 0); + assertEq(proxyAsImplementation.currencyRatioPriority(makeAddr("ALICE")), 0); } function test_flipRatio_succeeds() public { vm.chainId(1); // bc price = token1/token0 - assertTrue(positionDescriptor.flipRatio(USDC, WETH9)); - assertFalse(positionDescriptor.flipRatio(DAI, USDC)); - assertFalse(positionDescriptor.flipRatio(WBTC, WETH9)); - assertFalse(positionDescriptor.flipRatio(WBTC, USDC)); - assertFalse(positionDescriptor.flipRatio(WBTC, DAI)); + assertTrue(proxyAsImplementation.flipRatio(USDC, WETH9)); + assertFalse(proxyAsImplementation.flipRatio(DAI, USDC)); + assertFalse(proxyAsImplementation.flipRatio(WBTC, WETH9)); + assertFalse(proxyAsImplementation.flipRatio(WBTC, USDC)); + assertFalse(proxyAsImplementation.flipRatio(WBTC, DAI)); } function test_tokenURI_succeeds() public { @@ -112,7 +112,7 @@ contract PositionDescriptorTest is Test, PosmTestSetup { // The prefix length is calculated by converting the string to bytes and finding its length uint256 prefixLength = bytes("data:application/json;base64,").length; - string memory uri = positionDescriptor.tokenURI(lpm, tokenId); + string memory uri = proxyAsImplementation.tokenURI(lpm, tokenId); // Convert the uri to bytes bytes memory uriBytes = bytes(uri); @@ -133,7 +133,7 @@ contract PositionDescriptorTest is Test, PosmTestSetup { } // quote is currency1, base is currency0 - assertFalse(positionDescriptor.flipRatio(Currency.unwrap(key.currency0), Currency.unwrap(key.currency1))); + assertFalse(proxyAsImplementation.flipRatio(Currency.unwrap(key.currency0), Currency.unwrap(key.currency1))); string memory symbol0 = SafeCurrencyMetadata.currencySymbol(Currency.unwrap(currency0), nativeCurrencyLabel); string memory symbol1 = SafeCurrencyMetadata.currencySymbol(Currency.unwrap(currency1), nativeCurrencyLabel); @@ -231,7 +231,7 @@ contract PositionDescriptorTest is Test, PosmTestSetup { // The prefix length is calculated by converting the string to bytes and finding its length uint256 prefixLength = bytes("data:application/json;base64,").length; - string memory uri = positionDescriptor.tokenURI(lpm, tokenId); + string memory uri = proxyAsImplementation.tokenURI(lpm, tokenId); // Convert the uri to bytes bytes memory uriBytes = bytes(uri); @@ -253,7 +253,7 @@ contract PositionDescriptorTest is Test, PosmTestSetup { // quote is currency1, base is currency0 assertFalse( - positionDescriptor.flipRatio(Currency.unwrap(nativeKey.currency0), Currency.unwrap(nativeKey.currency1)) + proxyAsImplementation.flipRatio(Currency.unwrap(nativeKey.currency0), Currency.unwrap(nativeKey.currency1)) ); string memory symbol0 = @@ -354,7 +354,7 @@ contract PositionDescriptorTest is Test, PosmTestSetup { vm.expectRevert(abi.encodeWithSelector(IPositionDescriptor.InvalidTokenId.selector, tokenId + 1)); - positionDescriptor.tokenURI(lpm, tokenId + 1); + proxyAsImplementation.tokenURI(lpm, tokenId + 1); } // Helper functions for testing purposes diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index 58392a9f..c077cb4d 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -806,7 +806,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // Set the fee on transfer amount 1% higher. (uint256 amount0, uint256 amount1) = - fotKey.currency0 == Currency.wrap(address(fotToken)) ? (100e18, 99e18) : (99e19, 100e18); + fotKey.currency0 == Currency.wrap(address(fotToken)) ? (100e18, 99e18) : (99e18, 100e18); Plan memory planner = Planner.init(); planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, amount0, true)); @@ -821,7 +821,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF lpm.modifyLiquidities(actions, _deadline); (uint256 amount0AfterTransfer, uint256 amount1AfterTransfer) = - fotKey.currency0 == Currency.wrap(address(fotToken)) ? (99e18, 100e18) : (100e18, 99e19); + fotKey.currency0 == Currency.wrap(address(fotToken)) ? (99e18, 100e18) : (100e18, 99e18); uint128 newLiquidity = LiquidityAmounts.getLiquidityForAmounts( SQRT_PRICE_1_1, diff --git a/test/shared/Deploy.sol b/test/shared/Deploy.sol index 4b671d8c..5eceac6d 100644 --- a/test/shared/Deploy.sol +++ b/test/shared/Deploy.sol @@ -6,6 +6,7 @@ import {IPositionDescriptor} from "../../src/interfaces/IPositionDescriptor.sol" import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {IV4Quoter} from "../../src/interfaces/IV4Quoter.sol"; import {IStateView} from "../../src/interfaces/IStateView.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; library Deploy { Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); @@ -41,6 +42,18 @@ library Deploy { } } + function transparentUpgradeableProxy(address implementation, address admin, bytes memory data, bytes memory salt) + internal + returns (TransparentUpgradeableProxy proxy) + { + bytes memory args = abi.encode(implementation, admin, data); + bytes memory initcode = + abi.encodePacked(vm.getCode("TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy"), args); + assembly { + proxy := create2(0, add(initcode, 0x20), mload(initcode), salt) + } + } + function positionDescriptor( address poolManager, address wrappedNative, diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index 8798220e..89c4491c 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -22,6 +22,7 @@ import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; import {SortTokens} from "@uniswap/v4-core/test/utils/SortTokens.sol"; import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {PositionConfig} from "../shared/PositionConfig.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; /// @notice A shared test contract that wraps the v4-core deployers contract and exposes basic liquidity operations on posm. contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { @@ -29,9 +30,12 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { IAllowanceTransfer permit2; IPositionDescriptor public positionDescriptor; + TransparentUpgradeableProxy proxy; + IPositionDescriptor proxyAsImplementation; HookSavesDelta hook; address hookAddr = address(uint160(Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); IWETH9 public _WETH9 = IWETH9(address(new WETH())); + address governance = address(0xABCD); HookModifyLiquidities hookModifyLiquidities; address hookModifyLiquiditiesAddr = address( @@ -69,9 +73,11 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { permit2 = IAllowanceTransfer(deployPermit2()); positionDescriptor = Deploy.positionDescriptor(address(poolManager), 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, "ETH", hex"00"); + proxy = Deploy.transparentUpgradeableProxy(address(positionDescriptor), governance, "", hex"03"); lpm = Deploy.positionManager( - address(poolManager), address(permit2), 100_000, address(positionDescriptor), address(_WETH9), hex"03" + address(poolManager), address(permit2), 100_000, address(proxy), address(_WETH9), hex"03" ); + proxyAsImplementation = IPositionDescriptor(address(proxy)); } function seedBalance(address to) internal { From b2c943bd6f38b5801aeedc1cf8cbe68846ee861d Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Thu, 9 Jan 2025 18:17:55 -0500 Subject: [PATCH 02/14] make native currency immutable bytes --- script/DeployPosm.s.sol | 4 +-- snapshots/BaseActionsRouterTest.json | 3 -- snapshots/PaymentsTests.json | 6 ---- snapshots/PosMGasTest.json | 43 --------------------------- snapshots/PositionDescriptorTest.json | 4 --- snapshots/QuoterTest.json | 15 ---------- snapshots/StateViewTest.json | 12 -------- snapshots/V4RouterTest.json | 27 ----------------- src/PositionDescriptor.sol | 23 ++++++++++---- test/shared/Deploy.sol | 4 +-- 10 files changed, 22 insertions(+), 119 deletions(-) delete mode 100644 snapshots/BaseActionsRouterTest.json delete mode 100644 snapshots/PaymentsTests.json delete mode 100644 snapshots/PosMGasTest.json delete mode 100644 snapshots/PositionDescriptorTest.json delete mode 100644 snapshots/QuoterTest.json delete mode 100644 snapshots/StateViewTest.json delete mode 100644 snapshots/V4RouterTest.json diff --git a/script/DeployPosm.s.sol b/script/DeployPosm.s.sol index c51c2ca4..1e969df2 100644 --- a/script/DeployPosm.s.sol +++ b/script/DeployPosm.s.sol @@ -17,11 +17,11 @@ contract DeployPosmTest is Script { address permit2, uint256 unsubscribeGasLimit, address wrappedNative, - string memory nativeCurrencyLabel + bytes32 nativeCurrencyLabelBytes ) public returns (IPositionDescriptor positionDescriptor, IPositionManager posm) { vm.startBroadcast(); - positionDescriptor = Deploy.positionDescriptor(poolManager, wrappedNative, nativeCurrencyLabel, hex"00"); + positionDescriptor = Deploy.positionDescriptor(poolManager, wrappedNative, nativeCurrencyLabelBytes, hex"00"); console2.log("PositionDescriptor", address(positionDescriptor)); posm = Deploy.positionManager( diff --git a/snapshots/BaseActionsRouterTest.json b/snapshots/BaseActionsRouterTest.json deleted file mode 100644 index d7241dbe..00000000 --- a/snapshots/BaseActionsRouterTest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "BaseActionsRouter_mock10commands": "63076" -} \ No newline at end of file diff --git a/snapshots/PaymentsTests.json b/snapshots/PaymentsTests.json deleted file mode 100644 index c3e810d1..00000000 --- a/snapshots/PaymentsTests.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "Payments_swap_settleFromCaller_takeAllToMsgSender": "133006", - "Payments_swap_settleFromCaller_takeAllToSpecifiedAddress": "134475", - "Payments_swap_settleWithBalance_takeAllToMsgSender": "126957", - "Payments_swap_settleWithBalance_takeAllToSpecifiedAddress": "127095" -} \ No newline at end of file diff --git a/snapshots/PosMGasTest.json b/snapshots/PosMGasTest.json deleted file mode 100644 index cc70748e..00000000 --- a/snapshots/PosMGasTest.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "PositionManager_burn_empty": "51102", - "PositionManager_burn_empty_native": "51102", - "PositionManager_burn_nonEmpty_native_withClose": "127695", - "PositionManager_burn_nonEmpty_native_withTakePair": "127137", - "PositionManager_burn_nonEmpty_withClose": "134600", - "PositionManager_burn_nonEmpty_withTakePair": "134043", - "PositionManager_collect_native": "147732", - "PositionManager_collect_sameRange": "156364", - "PositionManager_collect_withClose": "156364", - "PositionManager_collect_withTakePair": "155679", - "PositionManager_decreaseLiquidity_native": "113681", - "PositionManager_decreaseLiquidity_withClose": "121933", - "PositionManager_decreaseLiquidity_withTakePair": "121248", - "PositionManager_decrease_burnEmpty": "137500", - "PositionManager_decrease_burnEmpty_native": "130595", - "PositionManager_decrease_sameRange_allLiquidity": "134649", - "PositionManager_decrease_take_take": "122490", - "PositionManager_increaseLiquidity_erc20_withClose": "160652", - "PositionManager_increaseLiquidity_erc20_withSettlePair": "159563", - "PositionManager_increaseLiquidity_native": "143532", - "PositionManager_increase_autocompoundExactUnclaimedFees": "138231", - "PositionManager_increase_autocompoundExcessFeesCredit": "179593", - "PositionManager_increase_autocompound_clearExcess": "149511", - "PositionManager_mint_native": "367550", - "PositionManager_mint_nativeWithSweep_withClose": "376153", - "PositionManager_mint_nativeWithSweep_withSettlePair": "375348", - "PositionManager_mint_onSameTickLower": "319298", - "PositionManager_mint_onSameTickUpper": "319940", - "PositionManager_mint_sameRange": "245522", - "PositionManager_mint_settleWithBalance_sweep": "420760", - "PositionManager_mint_warmedPool_differentRange": "325316", - "PositionManager_mint_withClose": "421910", - "PositionManager_mint_withSettlePair": "420939", - "PositionManager_multicall_initialize_mint": "458237", - "PositionManager_permit": "79175", - "PositionManager_permit_secondPosition": "62075", - "PositionManager_permit_twice": "44975", - "PositionManager_subscribe": "87968", - "PositionManager_unsubscribe": "62697", - "position manager initcode hash (without constructor params, as uint256)": "81827502601055975118808937107769364319765058198432540518516360048852193272922", - "positionManager bytecode size": "23877" -} \ No newline at end of file diff --git a/snapshots/PositionDescriptorTest.json b/snapshots/PositionDescriptorTest.json deleted file mode 100644 index 45898923..00000000 --- a/snapshots/PositionDescriptorTest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "position descriptor initcode hash (without constructor params, as uint256)": "88482580191959945449130293370700011665153263709859488839371600440410373093991", - "positionDescriptor bytecode size": "1488" -} \ No newline at end of file diff --git a/snapshots/QuoterTest.json b/snapshots/QuoterTest.json deleted file mode 100644 index a3c80a4f..00000000 --- a/snapshots/QuoterTest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Quoter_exactInputSingle_oneForZero_multiplePositions": "145902", - "Quoter_exactInputSingle_zeroForOne_multiplePositions": "152117", - "Quoter_exactOutputSingle_oneForZero": "79267", - "Quoter_exactOutputSingle_zeroForOne": "84512", - "Quoter_quoteExactInput_oneHop_1TickLoaded": "122728", - "Quoter_quoteExactInput_oneHop_initializedAfter": "147363", - "Quoter_quoteExactInput_oneHop_startingInitialized": "80638", - "Quoter_quoteExactInput_twoHops": "204942", - "Quoter_quoteExactOutput_oneHop_1TickLoaded": "122224", - "Quoter_quoteExactOutput_oneHop_2TicksLoaded": "152879", - "Quoter_quoteExactOutput_oneHop_initializedAfter": "122251", - "Quoter_quoteExactOutput_oneHop_startingInitialized": "98545", - "Quoter_quoteExactOutput_twoHops": "204670" -} \ No newline at end of file diff --git a/snapshots/StateViewTest.json b/snapshots/StateViewTest.json deleted file mode 100644 index dc141e39..00000000 --- a/snapshots/StateViewTest.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "StateView_extsload_getFeeGrowthGlobals": "2203", - "StateView_extsload_getFeeGrowthInside": "7875", - "StateView_extsload_getLiquidity": "1439", - "StateView_extsload_getPositionInfo": "2761", - "StateView_extsload_getPositionLiquidity": "1691", - "StateView_extsload_getSlot0": "1486", - "StateView_extsload_getTickBitmap": "1432", - "StateView_extsload_getTickFeeGrowthOutside": "2490", - "StateView_extsload_getTickInfo": "2693", - "StateView_extsload_getTickLiquidity": "1686" -} \ No newline at end of file diff --git a/snapshots/V4RouterTest.json b/snapshots/V4RouterTest.json deleted file mode 100644 index 952f619d..00000000 --- a/snapshots/V4RouterTest.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "V4Router_Bytecode": "8975", - "V4Router_ExactIn1Hop_nativeIn": "121653", - "V4Router_ExactIn1Hop_nativeOut": "120119", - "V4Router_ExactIn1Hop_oneForZero": "128991", - "V4Router_ExactIn1Hop_zeroForOne": "135517", - "V4Router_ExactIn2Hops": "192843", - "V4Router_ExactIn2Hops_nativeIn": "178979", - "V4Router_ExactIn3Hops": "250218", - "V4Router_ExactIn3Hops_nativeIn": "236354", - "V4Router_ExactInputSingle": "134001", - "V4Router_ExactInputSingle_nativeIn": "120137", - "V4Router_ExactInputSingle_nativeOut": "118581", - "V4Router_ExactOut1Hop_nativeIn_sweepETH": "127940", - "V4Router_ExactOut1Hop_nativeOut": "121329", - "V4Router_ExactOut1Hop_oneForZero": "130201", - "V4Router_ExactOut1Hop_zeroForOne": "134858", - "V4Router_ExactOut2Hops": "191291", - "V4Router_ExactOut2Hops_nativeIn": "184373", - "V4Router_ExactOut3Hops": "247788", - "V4Router_ExactOut3Hops_nativeIn": "240870", - "V4Router_ExactOut3Hops_nativeOut": "224943", - "V4Router_ExactOutputSingle": "133337", - "V4Router_ExactOutputSingle_nativeIn_sweepETH": "126419", - "V4Router_ExactOutputSingle_nativeOut": "119821", - "router initcode hash (without constructor params, as uint256)": "27545762869727400677117557485685740862616789454191614676777323590122002226479" -} \ No newline at end of file diff --git a/src/PositionDescriptor.sol b/src/PositionDescriptor.sol index 05fb0cc2..5b54ff6a 100644 --- a/src/PositionDescriptor.sol +++ b/src/PositionDescriptor.sol @@ -26,14 +26,27 @@ contract PositionDescriptor is IPositionDescriptor { address private constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; address public immutable wrappedNative; - string public nativeCurrencyLabel; + bytes32 public immutable nativeCurrencyLabelBytes; IPoolManager public immutable poolManager; - constructor(IPoolManager _poolManager, address _wrappedNative, string memory _nativeCurrencyLabel) { + constructor(IPoolManager _poolManager, address _wrappedNative, bytes32 _nativeCurrencyLabelBytes) { poolManager = _poolManager; wrappedNative = _wrappedNative; - nativeCurrencyLabel = _nativeCurrencyLabel; + nativeCurrencyLabelBytes = _nativeCurrencyLabelBytes; + } + + /// @notice Returns the native currency label as a string + function nativeCurrencyLabel() public view returns (string memory) { + uint256 len = 0; + while (len < 32 && nativeCurrencyLabelBytes[len] != 0) { + len++; + } + bytes memory b = new bytes(len); + for (uint256 i = 0; i < len; i++) { + b[i] = nativeCurrencyLabelBytes[i]; + } + return string(b); } /// @inheritdoc IPositionDescriptor @@ -66,8 +79,8 @@ contract PositionDescriptor is IPositionDescriptor { tokenId: tokenId, quoteCurrency: quoteCurrency, baseCurrency: baseCurrency, - quoteCurrencySymbol: SafeCurrencyMetadata.currencySymbol(quoteCurrency, nativeCurrencyLabel), - baseCurrencySymbol: SafeCurrencyMetadata.currencySymbol(baseCurrency, nativeCurrencyLabel), + quoteCurrencySymbol: SafeCurrencyMetadata.currencySymbol(quoteCurrency, nativeCurrencyLabel()), + baseCurrencySymbol: SafeCurrencyMetadata.currencySymbol(baseCurrency, nativeCurrencyLabel()), quoteCurrencyDecimals: SafeCurrencyMetadata.currencyDecimals(quoteCurrency), baseCurrencyDecimals: SafeCurrencyMetadata.currencyDecimals(baseCurrency), flipRatio: _flipRatio, diff --git a/test/shared/Deploy.sol b/test/shared/Deploy.sol index 5eceac6d..cfb9a215 100644 --- a/test/shared/Deploy.sol +++ b/test/shared/Deploy.sol @@ -57,10 +57,10 @@ library Deploy { function positionDescriptor( address poolManager, address wrappedNative, - string memory nativeCurrencyLabel, + bytes32 nativeCurrencyLabelBytes, bytes memory salt ) internal returns (IPositionDescriptor descriptor) { - bytes memory args = abi.encode(poolManager, wrappedNative, nativeCurrencyLabel); + bytes memory args = abi.encode(poolManager, wrappedNative, nativeCurrencyLabelBytes); bytes memory initcode = abi.encodePacked(vm.getCode("PositionDescriptor.sol:PositionDescriptor"), args); assembly { descriptor := create2(0, add(initcode, 0x20), mload(initcode), salt) From 6e67c9028618221b3c66357a5abba3402aa4d1ca Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Thu, 9 Jan 2025 18:31:38 -0500 Subject: [PATCH 03/14] add back snapshots --- snapshots/BaseActionsRouterTest.json | 3 ++ snapshots/PaymentsTests.json | 6 ++++ snapshots/PosMGasTest.json | 43 +++++++++++++++++++++++++++ snapshots/PositionDescriptorTest.json | 4 +++ snapshots/QuoterTest.json | 15 ++++++++++ snapshots/StateViewTest.json | 12 ++++++++ snapshots/V4RouterTest.json | 27 +++++++++++++++++ 7 files changed, 110 insertions(+) create mode 100644 snapshots/BaseActionsRouterTest.json create mode 100644 snapshots/PaymentsTests.json create mode 100644 snapshots/PosMGasTest.json create mode 100644 snapshots/PositionDescriptorTest.json create mode 100644 snapshots/QuoterTest.json create mode 100644 snapshots/StateViewTest.json create mode 100644 snapshots/V4RouterTest.json diff --git a/snapshots/BaseActionsRouterTest.json b/snapshots/BaseActionsRouterTest.json new file mode 100644 index 00000000..d7241dbe --- /dev/null +++ b/snapshots/BaseActionsRouterTest.json @@ -0,0 +1,3 @@ +{ + "BaseActionsRouter_mock10commands": "63076" +} \ No newline at end of file diff --git a/snapshots/PaymentsTests.json b/snapshots/PaymentsTests.json new file mode 100644 index 00000000..c3e810d1 --- /dev/null +++ b/snapshots/PaymentsTests.json @@ -0,0 +1,6 @@ +{ + "Payments_swap_settleFromCaller_takeAllToMsgSender": "133006", + "Payments_swap_settleFromCaller_takeAllToSpecifiedAddress": "134475", + "Payments_swap_settleWithBalance_takeAllToMsgSender": "126957", + "Payments_swap_settleWithBalance_takeAllToSpecifiedAddress": "127095" +} \ No newline at end of file diff --git a/snapshots/PosMGasTest.json b/snapshots/PosMGasTest.json new file mode 100644 index 00000000..61cbf0c4 --- /dev/null +++ b/snapshots/PosMGasTest.json @@ -0,0 +1,43 @@ +{ + "PositionManager_burn_empty": "51102", + "PositionManager_burn_empty_native": "51102", + "PositionManager_burn_nonEmpty_native_withClose": "127695", + "PositionManager_burn_nonEmpty_native_withTakePair": "127137", + "PositionManager_burn_nonEmpty_withClose": "134600", + "PositionManager_burn_nonEmpty_withTakePair": "134043", + "PositionManager_collect_native": "147732", + "PositionManager_collect_sameRange": "156364", + "PositionManager_collect_withClose": "156364", + "PositionManager_collect_withTakePair": "155679", + "PositionManager_decreaseLiquidity_native": "113681", + "PositionManager_decreaseLiquidity_withClose": "121933", + "PositionManager_decreaseLiquidity_withTakePair": "121248", + "PositionManager_decrease_burnEmpty": "137500", + "PositionManager_decrease_burnEmpty_native": "130595", + "PositionManager_decrease_sameRange_allLiquidity": "134649", + "PositionManager_decrease_take_take": "122490", + "PositionManager_increaseLiquidity_erc20_withClose": "160652", + "PositionManager_increaseLiquidity_erc20_withSettlePair": "159563", + "PositionManager_increaseLiquidity_native": "143532", + "PositionManager_increase_autocompoundExactUnclaimedFees": "138231", + "PositionManager_increase_autocompoundExcessFeesCredit": "179593", + "PositionManager_increase_autocompound_clearExcess": "149511", + "PositionManager_mint_native": "367550", + "PositionManager_mint_nativeWithSweep_withClose": "376153", + "PositionManager_mint_nativeWithSweep_withSettlePair": "375348", + "PositionManager_mint_onSameTickLower": "319298", + "PositionManager_mint_onSameTickUpper": "319940", + "PositionManager_mint_sameRange": "245522", + "PositionManager_mint_settleWithBalance_sweep": "420760", + "PositionManager_mint_warmedPool_differentRange": "325316", + "PositionManager_mint_withClose": "421910", + "PositionManager_mint_withSettlePair": "420939", + "PositionManager_multicall_initialize_mint": "458237", + "PositionManager_permit": "79175", + "PositionManager_permit_secondPosition": "62075", + "PositionManager_permit_twice": "44963", + "PositionManager_subscribe": "87968", + "PositionManager_unsubscribe": "62697", + "position manager initcode hash (without constructor params, as uint256)": "81827502601055975118808937107769364319765058198432540518516360048852193272922", + "positionManager bytecode size": "23877" +} \ No newline at end of file diff --git a/snapshots/PositionDescriptorTest.json b/snapshots/PositionDescriptorTest.json new file mode 100644 index 00000000..f47e81a9 --- /dev/null +++ b/snapshots/PositionDescriptorTest.json @@ -0,0 +1,4 @@ +{ + "position descriptor initcode hash (without constructor params, as uint256)": "90002686278379416913385532438840669828848441637921711710845035729125835578244", + "positionDescriptor bytecode size": "1488" +} \ No newline at end of file diff --git a/snapshots/QuoterTest.json b/snapshots/QuoterTest.json new file mode 100644 index 00000000..a3c80a4f --- /dev/null +++ b/snapshots/QuoterTest.json @@ -0,0 +1,15 @@ +{ + "Quoter_exactInputSingle_oneForZero_multiplePositions": "145902", + "Quoter_exactInputSingle_zeroForOne_multiplePositions": "152117", + "Quoter_exactOutputSingle_oneForZero": "79267", + "Quoter_exactOutputSingle_zeroForOne": "84512", + "Quoter_quoteExactInput_oneHop_1TickLoaded": "122728", + "Quoter_quoteExactInput_oneHop_initializedAfter": "147363", + "Quoter_quoteExactInput_oneHop_startingInitialized": "80638", + "Quoter_quoteExactInput_twoHops": "204942", + "Quoter_quoteExactOutput_oneHop_1TickLoaded": "122224", + "Quoter_quoteExactOutput_oneHop_2TicksLoaded": "152879", + "Quoter_quoteExactOutput_oneHop_initializedAfter": "122251", + "Quoter_quoteExactOutput_oneHop_startingInitialized": "98545", + "Quoter_quoteExactOutput_twoHops": "204670" +} \ No newline at end of file diff --git a/snapshots/StateViewTest.json b/snapshots/StateViewTest.json new file mode 100644 index 00000000..dc141e39 --- /dev/null +++ b/snapshots/StateViewTest.json @@ -0,0 +1,12 @@ +{ + "StateView_extsload_getFeeGrowthGlobals": "2203", + "StateView_extsload_getFeeGrowthInside": "7875", + "StateView_extsload_getLiquidity": "1439", + "StateView_extsload_getPositionInfo": "2761", + "StateView_extsload_getPositionLiquidity": "1691", + "StateView_extsload_getSlot0": "1486", + "StateView_extsload_getTickBitmap": "1432", + "StateView_extsload_getTickFeeGrowthOutside": "2490", + "StateView_extsload_getTickInfo": "2693", + "StateView_extsload_getTickLiquidity": "1686" +} \ No newline at end of file diff --git a/snapshots/V4RouterTest.json b/snapshots/V4RouterTest.json new file mode 100644 index 00000000..952f619d --- /dev/null +++ b/snapshots/V4RouterTest.json @@ -0,0 +1,27 @@ +{ + "V4Router_Bytecode": "8975", + "V4Router_ExactIn1Hop_nativeIn": "121653", + "V4Router_ExactIn1Hop_nativeOut": "120119", + "V4Router_ExactIn1Hop_oneForZero": "128991", + "V4Router_ExactIn1Hop_zeroForOne": "135517", + "V4Router_ExactIn2Hops": "192843", + "V4Router_ExactIn2Hops_nativeIn": "178979", + "V4Router_ExactIn3Hops": "250218", + "V4Router_ExactIn3Hops_nativeIn": "236354", + "V4Router_ExactInputSingle": "134001", + "V4Router_ExactInputSingle_nativeIn": "120137", + "V4Router_ExactInputSingle_nativeOut": "118581", + "V4Router_ExactOut1Hop_nativeIn_sweepETH": "127940", + "V4Router_ExactOut1Hop_nativeOut": "121329", + "V4Router_ExactOut1Hop_oneForZero": "130201", + "V4Router_ExactOut1Hop_zeroForOne": "134858", + "V4Router_ExactOut2Hops": "191291", + "V4Router_ExactOut2Hops_nativeIn": "184373", + "V4Router_ExactOut3Hops": "247788", + "V4Router_ExactOut3Hops_nativeIn": "240870", + "V4Router_ExactOut3Hops_nativeOut": "224943", + "V4Router_ExactOutputSingle": "133337", + "V4Router_ExactOutputSingle_nativeIn_sweepETH": "126419", + "V4Router_ExactOutputSingle_nativeOut": "119821", + "router initcode hash (without constructor params, as uint256)": "27545762869727400677117557485685740862616789454191614676777323590122002226479" +} \ No newline at end of file From ba6c3cdc7ccc238c293cb0128ade2d3bd5d3f872 Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Fri, 10 Jan 2025 09:38:16 -0500 Subject: [PATCH 04/14] snapshot of both proxy and position descriptor bytecode --- snapshots/PositionDescriptorTest.json | 3 ++- test/PositionDescriptor.t.sol | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/snapshots/PositionDescriptorTest.json b/snapshots/PositionDescriptorTest.json index f47e81a9..8ca090f1 100644 --- a/snapshots/PositionDescriptorTest.json +++ b/snapshots/PositionDescriptorTest.json @@ -1,4 +1,5 @@ { "position descriptor initcode hash (without constructor params, as uint256)": "90002686278379416913385532438840669828848441637921711710845035729125835578244", - "positionDescriptor bytecode size": "1488" + "positionDescriptor bytecode size": "24138", + "proxy bytecode size": "1488" } \ No newline at end of file diff --git a/test/PositionDescriptor.t.sol b/test/PositionDescriptor.t.sol index 6d62e7dd..0d725cd0 100644 --- a/test/PositionDescriptor.t.sol +++ b/test/PositionDescriptor.t.sol @@ -48,7 +48,11 @@ contract PositionDescriptorTest is Test, PosmTestSetup { } function test_bytecodeSize_positionDescriptor() public { - vm.snapshotValue("positionDescriptor bytecode size", address(proxyAsImplementation).code.length); + vm.snapshotValue("positionDescriptor bytecode size", address(positionDescriptor).code.length); + } + + function test_bytecodeSize_proxy() public { + vm.snapshotValue("proxy bytecode size", address(proxyAsImplementation).code.length); } function test_setup_succeeds() public view { From 6f05aafe1d768971baed1061576ffcd77b05997f Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Fri, 10 Jan 2025 18:15:43 -0500 Subject: [PATCH 05/14] update interface, unit test --- src/interfaces/IPositionDescriptor.sol | 3 +++ test/PositionDescriptor.t.sol | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/interfaces/IPositionDescriptor.sol b/src/interfaces/IPositionDescriptor.sol index 92085217..fbaf73c6 100644 --- a/src/interfaces/IPositionDescriptor.sol +++ b/src/interfaces/IPositionDescriptor.sol @@ -32,6 +32,9 @@ interface IPositionDescriptor { /// @return The wrapped native token for this descriptor function wrappedNative() external view returns (address); + /// @return The native currency label bytes for this descriptor + function nativeCurrencyLabelBytes() external view returns (bytes32); + /// @return The native currency label for this descriptor function nativeCurrencyLabel() external view returns (string memory); diff --git a/test/PositionDescriptor.t.sol b/test/PositionDescriptor.t.sol index 0d725cd0..0f4b4edc 100644 --- a/test/PositionDescriptor.t.sol +++ b/test/PositionDescriptor.t.sol @@ -26,6 +26,7 @@ contract PositionDescriptorTest is Test, PosmTestSetup { address public TBTC = 0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa; address public WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; string public nativeCurrencyLabel = "ETH"; + bytes32 public nativeCurrencyLabelBytes = "ETH"; struct Token { string description; @@ -58,6 +59,10 @@ contract PositionDescriptorTest is Test, PosmTestSetup { function test_setup_succeeds() public view { assertEq(address(proxyAsImplementation.poolManager()), address(manager)); assertEq(proxyAsImplementation.wrappedNative(), WETH9); + assertEq(proxyAsImplementation.nativeCurrencyLabelBytes(), nativeCurrencyLabelBytes); + } + + function test_nativeCurrencyLabel_succeeds() public view { assertEq(proxyAsImplementation.nativeCurrencyLabel(), nativeCurrencyLabel); } From ccea1c1b15e9d4d76c23951ea74394b6593f4e4a Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Fri, 10 Jan 2025 23:16:31 -0500 Subject: [PATCH 06/14] fix test --- .../position-managers/PositionManager.modifyLiquidities.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index c077cb4d..e82981d3 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -919,14 +919,14 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); // bool positionIsEntirelyInOtherToken = currency0IsFOT // ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) - // : tickLower > TickMath.getTickAtSqrtPrice(sqrtPriceX96); + // : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96); // if (bips == 10000 && !positionIsEntirelyInOtherToken) { if ( bips == 10000 && !( fotKey.currency0 == Currency.wrap(address(fotToken)) ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) - : tickLower > TickMath.getTickAtSqrtPrice(sqrtPriceX96) + : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96) ) ) { vm.expectRevert(Position.CannotUpdateEmptyPosition.selector); From 4ddacf8ed5f4585ed26bba0b6b0cdb34bf0b99ee Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Mon, 13 Jan 2025 12:45:34 -0500 Subject: [PATCH 07/14] run ci on stable version of foundry --- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b0eb346e..a25d4179 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,7 +19,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - name: Check format run: forge fmt --check diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 73de4cdb..bae1823a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - name: Run tests run: forge test --isolate -vvv From 88617c1d88510ebfdb1236656082f3a49ef83a46 Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Mon, 13 Jan 2025 15:04:24 -0500 Subject: [PATCH 08/14] unit test native currency label --- test/PositionDescriptor.t.sol | 8 +++++++- test/shared/PosmTestSetup.sol | 14 +++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/test/PositionDescriptor.t.sol b/test/PositionDescriptor.t.sol index 0f4b4edc..309e91b1 100644 --- a/test/PositionDescriptor.t.sol +++ b/test/PositionDescriptor.t.sol @@ -62,8 +62,14 @@ contract PositionDescriptorTest is Test, PosmTestSetup { assertEq(proxyAsImplementation.nativeCurrencyLabelBytes(), nativeCurrencyLabelBytes); } - function test_nativeCurrencyLabel_succeeds() public view { + function test_nativeCurrencyLabel_succeeds() public { assertEq(proxyAsImplementation.nativeCurrencyLabel(), nativeCurrencyLabel); + IPositionDescriptor polDescriptor = deployDescriptor(manager, "POL"); + assertEq(polDescriptor.nativeCurrencyLabel(), "POL"); + IPositionDescriptor bnbDescriptor = deployDescriptor(manager, "BNB"); + assertEq(bnbDescriptor.nativeCurrencyLabel(), "BNB"); + IPositionDescriptor avaxDescriptor = deployDescriptor(manager, "AVAX"); + assertEq(avaxDescriptor.nativeCurrencyLabel(), "AVAX"); } function test_currencyRatioPriority_mainnet_succeeds() public { diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index 89c4491c..f3003e1e 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -71,13 +71,17 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { function deployPosm(IPoolManager poolManager) internal { // We use deployPermit2() to prevent having to use via-ir in this repository. permit2 = IAllowanceTransfer(deployPermit2()); - positionDescriptor = - Deploy.positionDescriptor(address(poolManager), 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, "ETH", hex"00"); - proxy = Deploy.transparentUpgradeableProxy(address(positionDescriptor), governance, "", hex"03"); + proxyAsImplementation = deployDescriptor(poolManager, "ETH"); lpm = Deploy.positionManager( - address(poolManager), address(permit2), 100_000, address(proxy), address(_WETH9), hex"03" + address(poolManager), address(permit2), 100_000, address(proxyAsImplementation), address(_WETH9), hex"03" ); - proxyAsImplementation = IPositionDescriptor(address(proxy)); + } + + function deployDescriptor(IPoolManager poolManager, bytes32 label) internal returns (IPositionDescriptor) { + positionDescriptor = + Deploy.positionDescriptor(address(poolManager), 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, label, hex"00"); + proxy = Deploy.transparentUpgradeableProxy(address(positionDescriptor), governance, "", hex"03"); + return IPositionDescriptor(address(proxy)); } function seedBalance(address to) internal { From a0268c284e6699a17445e9f6d712e8cf505b4731 Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Mon, 13 Jan 2025 16:52:59 -0500 Subject: [PATCH 09/14] make nativecurrencylabelbytes private --- snapshots/PosMGasTest.json | 4 ++-- snapshots/PositionDescriptorTest.json | 4 ++-- src/PositionDescriptor.sol | 2 +- src/interfaces/IPositionDescriptor.sol | 3 --- test/PositionDescriptor.t.sol | 1 - 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/snapshots/PosMGasTest.json b/snapshots/PosMGasTest.json index 61cbf0c4..579fa664 100644 --- a/snapshots/PosMGasTest.json +++ b/snapshots/PosMGasTest.json @@ -33,9 +33,9 @@ "PositionManager_mint_withClose": "421910", "PositionManager_mint_withSettlePair": "420939", "PositionManager_multicall_initialize_mint": "458237", - "PositionManager_permit": "79175", + "PositionManager_permit": "79163", "PositionManager_permit_secondPosition": "62075", - "PositionManager_permit_twice": "44963", + "PositionManager_permit_twice": "44975", "PositionManager_subscribe": "87968", "PositionManager_unsubscribe": "62697", "position manager initcode hash (without constructor params, as uint256)": "81827502601055975118808937107769364319765058198432540518516360048852193272922", diff --git a/snapshots/PositionDescriptorTest.json b/snapshots/PositionDescriptorTest.json index 8ca090f1..a9f6400b 100644 --- a/snapshots/PositionDescriptorTest.json +++ b/snapshots/PositionDescriptorTest.json @@ -1,5 +1,5 @@ { - "position descriptor initcode hash (without constructor params, as uint256)": "90002686278379416913385532438840669828848441637921711710845035729125835578244", - "positionDescriptor bytecode size": "24138", + "position descriptor initcode hash (without constructor params, as uint256)": "62242073579002066175147720437850721791653757771535856244007756965162378120375", + "positionDescriptor bytecode size": "24069", "proxy bytecode size": "1488" } \ No newline at end of file diff --git a/src/PositionDescriptor.sol b/src/PositionDescriptor.sol index 5b54ff6a..3aa744ee 100644 --- a/src/PositionDescriptor.sol +++ b/src/PositionDescriptor.sol @@ -26,7 +26,7 @@ contract PositionDescriptor is IPositionDescriptor { address private constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; address public immutable wrappedNative; - bytes32 public immutable nativeCurrencyLabelBytes; + bytes32 private immutable nativeCurrencyLabelBytes; IPoolManager public immutable poolManager; diff --git a/src/interfaces/IPositionDescriptor.sol b/src/interfaces/IPositionDescriptor.sol index fbaf73c6..92085217 100644 --- a/src/interfaces/IPositionDescriptor.sol +++ b/src/interfaces/IPositionDescriptor.sol @@ -32,9 +32,6 @@ interface IPositionDescriptor { /// @return The wrapped native token for this descriptor function wrappedNative() external view returns (address); - /// @return The native currency label bytes for this descriptor - function nativeCurrencyLabelBytes() external view returns (bytes32); - /// @return The native currency label for this descriptor function nativeCurrencyLabel() external view returns (string memory); diff --git a/test/PositionDescriptor.t.sol b/test/PositionDescriptor.t.sol index 309e91b1..924fdced 100644 --- a/test/PositionDescriptor.t.sol +++ b/test/PositionDescriptor.t.sol @@ -59,7 +59,6 @@ contract PositionDescriptorTest is Test, PosmTestSetup { function test_setup_succeeds() public view { assertEq(address(proxyAsImplementation.poolManager()), address(manager)); assertEq(proxyAsImplementation.wrappedNative(), WETH9); - assertEq(proxyAsImplementation.nativeCurrencyLabelBytes(), nativeCurrencyLabelBytes); } function test_nativeCurrencyLabel_succeeds() public { From 76b010067b02e5dde9fcee12e742d76f690a96fe Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Tue, 14 Jan 2025 12:59:56 -0500 Subject: [PATCH 10/14] cannot redeem for other token if position is entirely in 1 token --- .../PositionManager.modifyLiquidities.t.sol | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index e82981d3..2646c085 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -981,4 +981,141 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF assertEq(lpm.getPositionLiquidity(tokenId), 0); } } + + function test_fuzz_mintFromDeltas_burn_maxFot_cannotRedeemBothTokens( + uint256 amount0, + uint256 amount1, + int24 tickLower, + int24 tickUpper + ) public { + MockFOT(address(fotToken)).setFee(10_000); + tickLower = int24( + bound( + tickLower, + fotKey.tickSpacing * (TickMath.MIN_TICK / fotKey.tickSpacing), + fotKey.tickSpacing * (TickMath.MAX_TICK / fotKey.tickSpacing) + ) + ); + tickUpper = int24( + bound( + tickUpper, + fotKey.tickSpacing * (TickMath.MIN_TICK / fotKey.tickSpacing), + fotKey.tickSpacing * (TickMath.MAX_TICK / fotKey.tickSpacing) + ) + ); + + tickLower = fotKey.tickSpacing * (tickLower / fotKey.tickSpacing); + tickUpper = fotKey.tickSpacing * (tickUpper / fotKey.tickSpacing); + vm.assume(tickUpper > tickLower); + + (uint160 sqrtPriceX96,,,) = manager.getSlot0(fotKey.toId()); + { + uint128 maxLiquidityPerTick = Pool.tickSpacingToMaxLiquidityPerTick(fotKey.tickSpacing); + (uint256 maxAmount0, uint256 maxAmount1) = LiquidityAmounts.getAmountsForLiquidity( + sqrtPriceX96, + TickMath.getSqrtPriceAtTick(tickLower), + TickMath.getSqrtPriceAtTick(tickUpper), + maxLiquidityPerTick + ); + + maxAmount0 = maxAmount0 == 0 ? 1 : maxAmount0 > STARTING_USER_BALANCE ? STARTING_USER_BALANCE : maxAmount0; + maxAmount1 = maxAmount1 == 0 ? 1 : maxAmount1 > STARTING_USER_BALANCE ? STARTING_USER_BALANCE : maxAmount1; + amount0 = bound(amount0, 1, maxAmount0); + amount1 = bound(amount1, 1, maxAmount1); + } + + uint256 tokenId = lpm.nextTokenId(); + + BalanceDiff memory balance0 = BalanceDiff(fotKey.currency0.balanceOf(address(this)), 0); + BalanceDiff memory balance1 = BalanceDiff(fotKey.currency1.balanceOf(address(this)), 0); + BalanceDiff memory balance0PM = BalanceDiff(fotKey.currency0.balanceOf(address(manager)), 0); + BalanceDiff memory balance1PM = BalanceDiff(fotKey.currency1.balanceOf(address(manager)), 0); + + Plan memory planner = Planner.init(); + + planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, amount0, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, amount1, true)); + planner.add( + Actions.MINT_POSITION_FROM_DELTAS, + abi.encode( + fotKey, + tickLower, + tickUpper, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + ActionConstants.MSG_SENDER, + ZERO_BYTES + ) + ); + // take the excess of each currency + planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); + + // needed to remove variables because of stack too deep + // Read below as: + // bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); + // bool positionIsEntirelyInOtherToken = currency0IsFOT + // ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) + // : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96); + // if (positionIsEntirelyInOtherToken) { + if ( + fotKey.currency0 == Currency.wrap(address(fotToken)) + ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) + : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96) + ) { + // MINT FROM DELTAS. + lpm.modifyLiquidities(planner.encode(), _deadline); + + balance0._after = fotKey.currency0.balanceOf(address(this)); + balance1._after = fotKey.currency1.balanceOf(address(this)); + balance0PM._after = fotKey.currency0.balanceOf(address(manager)); + balance1PM._after = fotKey.currency1.balanceOf(address(manager)); + + // Calculate the expected resulting balances used to create liquidity after the fee is applied. + Balance memory expected; + { + bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); + uint256 expectedFee = (currency0IsFOT ? amount0 : amount1).calculatePortion(10_000); + (expected._0, expected._1) = currency0IsFOT + ? (balance0._before - balance0._after - expectedFee, balance1._before - balance1._after) + : (balance0._before - balance0._after, balance1._before - balance1._after - expectedFee); + } + assertEq(expected._0, balance0PM._after - balance0PM._before); + assertEq(expected._1, balance1PM._after - balance1PM._before); + { + // the liquidity that was created is a diff of the balance change + uint128 expectedLiquidity = LiquidityAmounts.getLiquidityForAmounts( + sqrtPriceX96, + TickMath.getSqrtPriceAtTick(tickLower), + TickMath.getSqrtPriceAtTick(tickUpper), + expected._0, + expected._1 + ); + + assertEq(IERC721(address(lpm)).ownerOf(tokenId), address(this)); + assertEq(lpm.getPositionLiquidity(tokenId), expectedLiquidity); + } + // BURN. + planner = Planner.init(); + // Note that the slippage does not include the fee from the transfer. + planner.add( + Actions.BURN_POSITION, + abi.encode( + tokenId, expected._0 == 0 ? 0 : expected._0 - 1, expected._1 == 0 ? 0 : expected._1 - 1, ZERO_BYTES + ) + ); + + planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); + + // set fee to 0 to make sure the liquidity provider cannot redeem any fot token since the position is entirely in the other token. + MockFOT(address(fotToken)).setFee(0); + + lpm.modifyLiquidities(planner.encode(), _deadline); + + // After redeeming the position, the liquidity provider should not have received any of the fot token since the position was entirely in the other token. + assertEq(fotKey.currency1.balanceOf(address(this)), balance1._after); + assertGe(fotKey.currency0.balanceOf(address(this)), balance0._after); + + assertEq(lpm.getPositionLiquidity(tokenId), 0); + } + } } From cce7374c3e7a182c910f09d7c925ee50be9beeed Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Tue, 14 Jan 2025 18:46:22 -0500 Subject: [PATCH 11/14] use sqrt price instead of tick to be more accurate --- .../PositionManager.modifyLiquidities.t.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index 2646c085..148598b4 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -918,15 +918,15 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // Read below as: // bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); // bool positionIsEntirelyInOtherToken = currency0IsFOT - // ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) - // : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96); + // ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 + // : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96; // if (bips == 10000 && !positionIsEntirelyInOtherToken) { if ( bips == 10000 && !( fotKey.currency0 == Currency.wrap(address(fotToken)) - ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) - : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96) + ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 + : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96 ) ) { vm.expectRevert(Position.CannotUpdateEmptyPosition.selector); @@ -1054,13 +1054,13 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // Read below as: // bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); // bool positionIsEntirelyInOtherToken = currency0IsFOT - // ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) - // : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96); + // ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 + // : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96; // if (positionIsEntirelyInOtherToken) { if ( fotKey.currency0 == Currency.wrap(address(fotToken)) - ? tickUpper <= TickMath.getTickAtSqrtPrice(sqrtPriceX96) - : tickLower >= TickMath.getTickAtSqrtPrice(sqrtPriceX96) + ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 + : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96 ) { // MINT FROM DELTAS. lpm.modifyLiquidities(planner.encode(), _deadline); From bf6a92b870c0c31cf8845279e9032c645db470d1 Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Fri, 17 Jan 2025 12:23:51 -0500 Subject: [PATCH 12/14] etch weth address --- test/PositionDescriptor.t.sol | 2 +- test/shared/PosmTestSetup.sol | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/test/PositionDescriptor.t.sol b/test/PositionDescriptor.t.sol index 924fdced..38360358 100644 --- a/test/PositionDescriptor.t.sol +++ b/test/PositionDescriptor.t.sol @@ -19,7 +19,7 @@ import {Descriptor} from "../src/libraries/Descriptor.sol"; contract PositionDescriptorTest is Test, PosmTestSetup { using Base64 for string; - address public WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address public WETH9 = makeAddr("WETH"); address public DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address public USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; address public USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7; diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index f3003e1e..13c2f69a 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -34,7 +34,10 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { IPositionDescriptor proxyAsImplementation; HookSavesDelta hook; address hookAddr = address(uint160(Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); - IWETH9 public _WETH9 = IWETH9(address(new WETH())); + + WETH wethImpl = new WETH(); + IWETH9 public _WETH9; + address governance = address(0xABCD); HookModifyLiquidities hookModifyLiquidities; @@ -71,15 +74,21 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { function deployPosm(IPoolManager poolManager) internal { // We use deployPermit2() to prevent having to use via-ir in this repository. permit2 = IAllowanceTransfer(deployPermit2()); + _WETH9 = deployWETH(); proxyAsImplementation = deployDescriptor(poolManager, "ETH"); lpm = Deploy.positionManager( address(poolManager), address(permit2), 100_000, address(proxyAsImplementation), address(_WETH9), hex"03" ); } + function deployWETH() internal returns (IWETH9) { + address wethAddr = makeAddr("WETH"); + vm.etch(wethAddr, address(wethImpl).code); + return IWETH9(wethAddr); + } + function deployDescriptor(IPoolManager poolManager, bytes32 label) internal returns (IPositionDescriptor) { - positionDescriptor = - Deploy.positionDescriptor(address(poolManager), 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, label, hex"00"); + positionDescriptor = Deploy.positionDescriptor(address(poolManager), address(_WETH9), label, hex"00"); proxy = Deploy.transparentUpgradeableProxy(address(positionDescriptor), governance, "", hex"03"); return IPositionDescriptor(address(proxy)); } From c109924b82e9bca7a3c75461ee2546e84a5a7f72 Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Fri, 17 Jan 2025 14:48:17 -0500 Subject: [PATCH 13/14] add liquidity beforehand --- .../PositionManager.modifyLiquidities.t.sol | 128 ++++++++---------- 1 file changed, 57 insertions(+), 71 deletions(-) diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index 148598b4..c2f5b0fc 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -982,59 +982,18 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF } } - function test_fuzz_mintFromDeltas_burn_maxFot_cannotRedeemBothTokens( - uint256 amount0, - uint256 amount1, - int24 tickLower, - int24 tickUpper - ) public { - MockFOT(address(fotToken)).setFee(10_000); - tickLower = int24( - bound( - tickLower, - fotKey.tickSpacing * (TickMath.MIN_TICK / fotKey.tickSpacing), - fotKey.tickSpacing * (TickMath.MAX_TICK / fotKey.tickSpacing) - ) - ); - tickUpper = int24( - bound( - tickUpper, - fotKey.tickSpacing * (TickMath.MIN_TICK / fotKey.tickSpacing), - fotKey.tickSpacing * (TickMath.MAX_TICK / fotKey.tickSpacing) - ) - ); - - tickLower = fotKey.tickSpacing * (tickLower / fotKey.tickSpacing); - tickUpper = fotKey.tickSpacing * (tickUpper / fotKey.tickSpacing); - vm.assume(tickUpper > tickLower); - + function test_mintFromDeltas_burn_maxFot_cannotRedeemBothTokens() public { + int24 tickUpper = 60; (uint160 sqrtPriceX96,,,) = manager.getSlot0(fotKey.toId()); - { - uint128 maxLiquidityPerTick = Pool.tickSpacingToMaxLiquidityPerTick(fotKey.tickSpacing); - (uint256 maxAmount0, uint256 maxAmount1) = LiquidityAmounts.getAmountsForLiquidity( - sqrtPriceX96, - TickMath.getSqrtPriceAtTick(tickLower), - TickMath.getSqrtPriceAtTick(tickUpper), - maxLiquidityPerTick - ); - - maxAmount0 = maxAmount0 == 0 ? 1 : maxAmount0 > STARTING_USER_BALANCE ? STARTING_USER_BALANCE : maxAmount0; - maxAmount1 = maxAmount1 == 0 ? 1 : maxAmount1 > STARTING_USER_BALANCE ? STARTING_USER_BALANCE : maxAmount1; - amount0 = bound(amount0, 1, maxAmount0); - amount1 = bound(amount1, 1, maxAmount1); - } + // current tick is 0, tickLower is -60 + int24 tickLower = TickMath.getTickAtSqrtPrice(sqrtPriceX96) - fotKey.tickSpacing; uint256 tokenId = lpm.nextTokenId(); - BalanceDiff memory balance0 = BalanceDiff(fotKey.currency0.balanceOf(address(this)), 0); - BalanceDiff memory balance1 = BalanceDiff(fotKey.currency1.balanceOf(address(this)), 0); - BalanceDiff memory balance0PM = BalanceDiff(fotKey.currency0.balanceOf(address(manager)), 0); - BalanceDiff memory balance1PM = BalanceDiff(fotKey.currency1.balanceOf(address(manager)), 0); - Plan memory planner = Planner.init(); - planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, amount0, true)); - planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, amount1, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, 1 ether, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, 1 ether, true)); planner.add( Actions.MINT_POSITION_FROM_DELTAS, abi.encode( @@ -1050,19 +1009,51 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // take the excess of each currency planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); - // needed to remove variables because of stack too deep - // Read below as: - // bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); - // bool positionIsEntirelyInOtherToken = currency0IsFOT - // ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 - // : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96; - // if (positionIsEntirelyInOtherToken) { - if ( - fotKey.currency0 == Currency.wrap(address(fotToken)) - ? TickMath.getSqrtPriceAtTick(tickUpper) <= sqrtPriceX96 - : TickMath.getSqrtPriceAtTick(tickLower) >= sqrtPriceX96 - ) { + // alice adds the liquidity in range [-60, 60] + vm.prank(alice); + seedToken(fotToken, alice); + IERC20(Currency.unwrap(fotKey.currency1)).approve(address(permit2), type(uint256).max); + permit2.approve(Currency.unwrap(fotKey.currency1), alice, type(uint160).max, type(uint48).max); + lpm.modifyLiquidities(planner.encode(), _deadline); + vm.stopPrank(); + + // set tick lower to current tick, making the new position that will be added entirely in other token + // tickLower = 0 = current tick + tickLower = TickMath.getTickAtSqrtPrice(sqrtPriceX96); + + BalanceDiff memory balance0 = BalanceDiff(fotKey.currency0.balanceOf(address(this)), 0); + BalanceDiff memory balance1 = BalanceDiff(fotKey.currency1.balanceOf(address(this)), 0); + BalanceDiff memory balance0PM = BalanceDiff(fotKey.currency0.balanceOf(address(manager)), 0); + BalanceDiff memory balance1PM = BalanceDiff(fotKey.currency1.balanceOf(address(manager)), 0); + + // set fee of fotToken to 100% + MockFOT(address(fotToken)).setFee(10_000); + + // assume currency1 is fotToken + if (!(fotKey.currency0 == Currency.wrap(address(fotToken)))) { // MINT FROM DELTAS. + tokenId = lpm.nextTokenId(); + + planner = Planner.init(); + + planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, 1 ether, true)); + planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, 1 ether, true)); + planner.add( + Actions.MINT_POSITION_FROM_DELTAS, + abi.encode( + fotKey, + tickLower, + tickUpper, + MAX_SLIPPAGE_INCREASE, + MAX_SLIPPAGE_INCREASE, + ActionConstants.MSG_SENDER, + ZERO_BYTES + ) + ); + // take the excess of each currency + planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); + + // add liquidity lpm.modifyLiquidities(planner.encode(), _deadline); balance0._after = fotKey.currency0.balanceOf(address(this)); @@ -1073,13 +1064,13 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // Calculate the expected resulting balances used to create liquidity after the fee is applied. Balance memory expected; { - bool currency0IsFOT = fotKey.currency0 == Currency.wrap(address(fotToken)); - uint256 expectedFee = (currency0IsFOT ? amount0 : amount1).calculatePortion(10_000); - (expected._0, expected._1) = currency0IsFOT - ? (balance0._before - balance0._after - expectedFee, balance1._before - balance1._after) - : (balance0._before - balance0._after, balance1._before - balance1._after - expectedFee); + // expected fee is the same amount that was sent, since fee is now 100% + uint256 expectedFee = 1 ether; + (expected._0, expected._1) = + (balance0._before - balance0._after, balance1._before - balance1._after - expectedFee); } assertEq(expected._0, balance0PM._after - balance0PM._before); + // expected._1 is 0 because no fotToken was sent to PM because of 100% fee assertEq(expected._1, balance1PM._after - balance1PM._before); { // the liquidity that was created is a diff of the balance change @@ -1097,12 +1088,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // BURN. planner = Planner.init(); // Note that the slippage does not include the fee from the transfer. - planner.add( - Actions.BURN_POSITION, - abi.encode( - tokenId, expected._0 == 0 ? 0 : expected._0 - 1, expected._1 == 0 ? 0 : expected._1 - 1, ZERO_BYTES - ) - ); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, expected._0 - 1, 0, ZERO_BYTES)); planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); @@ -1113,7 +1099,7 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF // After redeeming the position, the liquidity provider should not have received any of the fot token since the position was entirely in the other token. assertEq(fotKey.currency1.balanceOf(address(this)), balance1._after); - assertGe(fotKey.currency0.balanceOf(address(this)), balance0._after); + assertGt(fotKey.currency0.balanceOf(address(this)), balance0._after); assertEq(lpm.getPositionLiquidity(tokenId), 0); } From ce67772fce8dd28ac7c554e7779184f9b610972a Mon Sep 17 00:00:00 2001 From: dianakocsis Date: Fri, 17 Jan 2025 15:24:01 -0500 Subject: [PATCH 14/14] remove test --- .../PositionManager.modifyLiquidities.t.sol | 123 ------------------ 1 file changed, 123 deletions(-) diff --git a/test/position-managers/PositionManager.modifyLiquidities.t.sol b/test/position-managers/PositionManager.modifyLiquidities.t.sol index c2f5b0fc..83bed801 100644 --- a/test/position-managers/PositionManager.modifyLiquidities.t.sol +++ b/test/position-managers/PositionManager.modifyLiquidities.t.sol @@ -981,127 +981,4 @@ contract PositionManagerModifyLiquiditiesTest is Test, PosmTestSetup, LiquidityF assertEq(lpm.getPositionLiquidity(tokenId), 0); } } - - function test_mintFromDeltas_burn_maxFot_cannotRedeemBothTokens() public { - int24 tickUpper = 60; - (uint160 sqrtPriceX96,,,) = manager.getSlot0(fotKey.toId()); - // current tick is 0, tickLower is -60 - int24 tickLower = TickMath.getTickAtSqrtPrice(sqrtPriceX96) - fotKey.tickSpacing; - - uint256 tokenId = lpm.nextTokenId(); - - Plan memory planner = Planner.init(); - - planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, 1 ether, true)); - planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, 1 ether, true)); - planner.add( - Actions.MINT_POSITION_FROM_DELTAS, - abi.encode( - fotKey, - tickLower, - tickUpper, - MAX_SLIPPAGE_INCREASE, - MAX_SLIPPAGE_INCREASE, - ActionConstants.MSG_SENDER, - ZERO_BYTES - ) - ); - // take the excess of each currency - planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); - - // alice adds the liquidity in range [-60, 60] - vm.prank(alice); - seedToken(fotToken, alice); - IERC20(Currency.unwrap(fotKey.currency1)).approve(address(permit2), type(uint256).max); - permit2.approve(Currency.unwrap(fotKey.currency1), alice, type(uint160).max, type(uint48).max); - lpm.modifyLiquidities(planner.encode(), _deadline); - vm.stopPrank(); - - // set tick lower to current tick, making the new position that will be added entirely in other token - // tickLower = 0 = current tick - tickLower = TickMath.getTickAtSqrtPrice(sqrtPriceX96); - - BalanceDiff memory balance0 = BalanceDiff(fotKey.currency0.balanceOf(address(this)), 0); - BalanceDiff memory balance1 = BalanceDiff(fotKey.currency1.balanceOf(address(this)), 0); - BalanceDiff memory balance0PM = BalanceDiff(fotKey.currency0.balanceOf(address(manager)), 0); - BalanceDiff memory balance1PM = BalanceDiff(fotKey.currency1.balanceOf(address(manager)), 0); - - // set fee of fotToken to 100% - MockFOT(address(fotToken)).setFee(10_000); - - // assume currency1 is fotToken - if (!(fotKey.currency0 == Currency.wrap(address(fotToken)))) { - // MINT FROM DELTAS. - tokenId = lpm.nextTokenId(); - - planner = Planner.init(); - - planner.add(Actions.SETTLE, abi.encode(fotKey.currency0, 1 ether, true)); - planner.add(Actions.SETTLE, abi.encode(fotKey.currency1, 1 ether, true)); - planner.add( - Actions.MINT_POSITION_FROM_DELTAS, - abi.encode( - fotKey, - tickLower, - tickUpper, - MAX_SLIPPAGE_INCREASE, - MAX_SLIPPAGE_INCREASE, - ActionConstants.MSG_SENDER, - ZERO_BYTES - ) - ); - // take the excess of each currency - planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); - - // add liquidity - lpm.modifyLiquidities(planner.encode(), _deadline); - - balance0._after = fotKey.currency0.balanceOf(address(this)); - balance1._after = fotKey.currency1.balanceOf(address(this)); - balance0PM._after = fotKey.currency0.balanceOf(address(manager)); - balance1PM._after = fotKey.currency1.balanceOf(address(manager)); - - // Calculate the expected resulting balances used to create liquidity after the fee is applied. - Balance memory expected; - { - // expected fee is the same amount that was sent, since fee is now 100% - uint256 expectedFee = 1 ether; - (expected._0, expected._1) = - (balance0._before - balance0._after, balance1._before - balance1._after - expectedFee); - } - assertEq(expected._0, balance0PM._after - balance0PM._before); - // expected._1 is 0 because no fotToken was sent to PM because of 100% fee - assertEq(expected._1, balance1PM._after - balance1PM._before); - { - // the liquidity that was created is a diff of the balance change - uint128 expectedLiquidity = LiquidityAmounts.getLiquidityForAmounts( - sqrtPriceX96, - TickMath.getSqrtPriceAtTick(tickLower), - TickMath.getSqrtPriceAtTick(tickUpper), - expected._0, - expected._1 - ); - - assertEq(IERC721(address(lpm)).ownerOf(tokenId), address(this)); - assertEq(lpm.getPositionLiquidity(tokenId), expectedLiquidity); - } - // BURN. - planner = Planner.init(); - // Note that the slippage does not include the fee from the transfer. - planner.add(Actions.BURN_POSITION, abi.encode(tokenId, expected._0 - 1, 0, ZERO_BYTES)); - - planner.add(Actions.TAKE_PAIR, abi.encode(fotKey.currency0, fotKey.currency1, ActionConstants.MSG_SENDER)); - - // set fee to 0 to make sure the liquidity provider cannot redeem any fot token since the position is entirely in the other token. - MockFOT(address(fotToken)).setFee(0); - - lpm.modifyLiquidities(planner.encode(), _deadline); - - // After redeeming the position, the liquidity provider should not have received any of the fot token since the position was entirely in the other token. - assertEq(fotKey.currency1.balanceOf(address(this)), balance1._after); - assertGt(fotKey.currency0.balanceOf(address(this)), balance0._after); - - assertEq(lpm.getPositionLiquidity(tokenId), 0); - } - } }