From d59846b640fef4f40091a4e55c61dac5b8e08122 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Sat, 27 Jul 2024 12:47:51 -0400 Subject: [PATCH 01/23] move to a base actions router --- .../PositionManager_burn_empty.snap | 2 +- .../PositionManager_burn_empty_native.snap | 2 +- .../PositionManager_burn_nonEmpty.snap | 2 +- .../PositionManager_burn_nonEmpty_native.snap | 2 +- .forge-snapshots/PositionManager_collect.snap | 2 +- .../PositionManager_collect_native.snap | 2 +- .../PositionManager_collect_sameRange.snap | 2 +- .../PositionManager_decreaseLiquidity.snap | 2 +- ...itionManager_decreaseLiquidity_native.snap | 2 +- .../PositionManager_decrease_burnEmpty.snap | 2 +- ...tionManager_decrease_burnEmpty_native.snap | 2 +- ...nager_decrease_sameRange_allLiquidity.snap | 2 +- ...sitionManager_increaseLiquidity_erc20.snap | 2 +- ...itionManager_increaseLiquidity_native.snap | 2 +- ...crease_autocompoundExactUnclaimedFees.snap | 2 +- ...increase_autocompoundExcessFeesCredit.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...anager_mint_warmedPool_differentRange.snap | 2 +- ...tionManager_multicall_initialize_mint.snap | 2 +- src/PositionManager.sol | 56 ++++++++----------- src/base/BaseActionsRouter.sol | 4 +- src/base/BaseActionsRouterReturns.sol | 55 ++++++++++++++++++ src/interfaces/IPositionManager.sol | 11 ---- src/libraries/Actions.sol | 4 ++ test/position-managers/Execute.t.sol | 11 ++-- test/position-managers/Gas.t.sol | 49 ++++++++-------- .../position-managers/IncreaseLiquidity.t.sol | 5 +- test/position-managers/NativeToken.t.sol | 3 +- .../PositionManager.multicall.t.sol | 5 +- test/position-managers/PositionManager.t.sol | 10 ++-- test/shared/LiquidityOperations.sol | 10 ++-- test/shared/Planner.sol | 11 ++-- test/shared/fuzz/LiquidityFuzzers.sol | 8 ++- 38 files changed, 172 insertions(+), 118 deletions(-) create mode 100644 src/base/BaseActionsRouterReturns.sol diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index ccdbe1ba..ccc8666e 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -50222 \ No newline at end of file +49205 \ 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 9ff61767..25c326cc 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -50040 \ No newline at end of file +49023 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty.snap b/.forge-snapshots/PositionManager_burn_nonEmpty.snap index b60fb958..2b7693b3 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty.snap @@ -1 +1 @@ -135866 \ No newline at end of file +134184 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap index 6dd8b18f..eb8ecc93 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap @@ -1 +1 @@ -128788 \ No newline at end of file +127105 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect.snap b/.forge-snapshots/PositionManager_collect.snap index 2f3bb39f..54e46516 100644 --- a/.forge-snapshots/PositionManager_collect.snap +++ b/.forge-snapshots/PositionManager_collect.snap @@ -1 +1 @@ -158157 \ No newline at end of file +156278 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index 2c55e112..0164ca2a 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -149309 \ No newline at end of file +147430 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index 2f3bb39f..54e46516 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -158157 \ No newline at end of file +156278 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity.snap b/.forge-snapshots/PositionManager_decreaseLiquidity.snap index a73bc079..c52c74b6 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity.snap @@ -1 +1 @@ -123700 \ No newline at end of file +121821 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index 601755bc..e4351f88 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -114922 \ No newline at end of file +113419 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index 4f68da3a..36edafd1 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -142193 \ No newline at end of file +140280 \ 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 cdb7010b..f8ac4b1e 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -134932 \ No newline at end of file +133019 \ 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 27de42fa..5081a8b0 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -136416 \ No newline at end of file +134537 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index f96eb326..378102d1 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -150444 \ No newline at end of file +148641 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index c6dec8eb..19228ded 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -135654 \ No newline at end of file +133851 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index eb87d8b0..a82ecf11 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -142305 \ No newline at end of file +140501 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index 627d3cfa..ce5490b5 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -178459 \ No newline at end of file +176655 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index f8026a08..37f10e0d 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -370660 \ No newline at end of file +368720 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 6ed6160c..30e2aca0 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -338770 \ No newline at end of file +336830 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index 1cdbf624..e2d6bd57 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -345708 \ No newline at end of file +343768 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index 4ee3daa6..c84f0131 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -313342 \ No newline at end of file +311402 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index b5f5d339..ff7f6612 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -313984 \ No newline at end of file +312044 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index 1dafa560..d1a17915 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -239566 \ No newline at end of file +237626 \ 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 b40b842e..87917a85 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -319360 \ No newline at end of file +317420 \ 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 0a0c6158..9ed80c5c 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -415150 \ No newline at end of file +413210 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 6a704dac..bb701bc6 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -14,12 +14,14 @@ import {ERC20} from "solmate/src/tokens/ERC20.sol"; import {ERC721Permit} from "./base/ERC721Permit.sol"; import {ReentrancyLock} from "./base/ReentrancyLock.sol"; -import {IPositionManager, Actions} from "./interfaces/IPositionManager.sol"; +import {IPositionManager} from "./interfaces/IPositionManager.sol"; import {SafeCallback} from "./base/SafeCallback.sol"; import {Multicall} from "./base/Multicall.sol"; import {PoolInitializer} from "./base/PoolInitializer.sol"; import {DeltaResolver} from "./base/DeltaResolver.sol"; import {PositionConfig, PositionConfigLibrary} from "./libraries/PositionConfig.sol"; +import {BaseActionsRouterReturns} from "./base/BaseActionsRouterReturns.sol"; +import {Actions} from "./libraries/Actions.sol"; contract PositionManager is IPositionManager, @@ -28,7 +30,8 @@ contract PositionManager is Multicall, SafeCallback, DeltaResolver, - ReentrancyLock + ReentrancyLock, + BaseActionsRouterReturns { using SafeTransferLib for *; using CurrencyLibrary for Currency; @@ -45,7 +48,7 @@ contract PositionManager is mapping(uint256 tokenId => bytes32 configId) public positionConfigs; constructor(IPoolManager _poolManager) - SafeCallback(_poolManager) + BaseActionsRouterReturns(_poolManager) ERC721Permit("Uniswap V4 Positions NFT", "UNI-V4-POSM", "1") {} @@ -63,39 +66,28 @@ contract PositionManager is checkDeadline(deadline) returns (bytes[] memory) { - // TODO: Edit the encoding/decoding. - return abi.decode(poolManager.unlock(unlockData), (bytes[])); + // For now POSM will bubble up sub call return values. + return _executeActions(unlockData); } - function _unlockCallback(bytes calldata payload) internal override returns (bytes memory) { - (Actions[] memory actions, bytes[] memory params) = abi.decode(payload, (Actions[], bytes[])); - - bytes[] memory returnData = _dispatch(actions, params); - - return abi.encode(returnData); + function _handleAction(uint256 action, bytes calldata params) internal override returns (bytes memory) { + if (action == Actions.INCREASE_LIQUIDITY) { + return _increase(params); + } else if (action == Actions.DECREASE_LIQUIDITY) { + return _decrease(params); + } else if (action == Actions.MINT_POSITION) { + return _mint(params); + } else if (action == Actions.CLOSE_CURRENCY) { + return _close(params); + } else if (action == Actions.BURN_POSITION) { + return _burn(params); + } else { + revert UnsupportedAction(action); + } } - function _dispatch(Actions[] memory actions, bytes[] memory params) internal returns (bytes[] memory returnData) { - uint256 length = actions.length; - if (length != params.length) revert MismatchedLengths(); - returnData = new bytes[](length); - for (uint256 i; i < length; i++) { - if (actions[i] == Actions.INCREASE) { - returnData[i] = _increase(params[i]); - } else if (actions[i] == Actions.DECREASE) { - returnData[i] = _decrease(params[i]); - } else if (actions[i] == Actions.MINT) { - // TODO: Mint will be coupled with increase. - returnData[i] = _mint(params[i]); - } else if (actions[i] == Actions.CLOSE_CURRENCY) { - returnData[i] = _close(params[i]); - } else if (actions[i] == Actions.BURN) { - // Will automatically decrease liquidity to 0 if the position is not already empty. - returnData[i] = _burn(params[i]); - } else { - revert UnsupportedAction(); - } - } + function _msgSender() internal view override returns (address) { + return _getLocker(); } /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes hookData diff --git a/src/base/BaseActionsRouter.sol b/src/base/BaseActionsRouter.sol index e88b1fe8..1cb1b50a 100644 --- a/src/base/BaseActionsRouter.sol +++ b/src/base/BaseActionsRouter.sol @@ -20,8 +20,8 @@ abstract contract BaseActionsRouter is SafeCallback { /// @notice internal function that triggers the execution of a set of actions on v4 /// @dev inheriting contracts should call this function to trigger execution - function _executeActions(bytes calldata params) internal { - poolManager.unlock(params); + function _executeActions(bytes calldata unlockData) internal { + poolManager.unlock(unlockData); } /// @notice function that is called by the PoolManager through the SafeCallback.unlockCallback diff --git a/src/base/BaseActionsRouterReturns.sol b/src/base/BaseActionsRouterReturns.sol new file mode 100644 index 00000000..ed4c6270 --- /dev/null +++ b/src/base/BaseActionsRouterReturns.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.24; + +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {SafeCallback} from "./SafeCallback.sol"; +import {CalldataDecoder} from "../libraries/CalldataDecoder.sol"; + +/// @notice Abstract contract for performing a combination of actions on Uniswap v4. +/// @dev Suggested uint256 action values are defined in Actions.sol, however any definition can be used +/// @dev This contract handles return values from sub calls to _handleAction. +abstract contract BaseActionsRouterReturns is SafeCallback { + using CalldataDecoder for bytes; + + /// @notice emitted when different numbers of parameters and actions are provided + error LengthMismatch(); + + /// @notice emitted when an inheriting contract does not support an action + error UnsupportedAction(uint256 action); + + constructor(IPoolManager _poolManager) SafeCallback(_poolManager) {} + + /// @notice internal function that triggers the execution of a set of actions on v4 + /// @dev inheriting contracts should call this function to trigger execution + function _executeActions(bytes calldata unlockData) internal returns (bytes[] memory) { + return abi.decode(poolManager.unlock(unlockData), (bytes[])); + } + + /// @notice function that is called by the PoolManager through the SafeCallback.unlockCallback + function _unlockCallback(bytes calldata data) internal override returns (bytes memory) { + // abi.decode(data, (uint256[], bytes[])); + (uint256[] calldata actions, bytes[] calldata params) = data.decodeActionsRouterParams(); + + uint256 numActions = actions.length; + if (numActions != params.length) revert LengthMismatch(); + + bytes[] memory results = new bytes[](numActions); + for (uint256 actionIndex = 0; actionIndex < numActions; actionIndex++) { + uint256 action = actions[actionIndex]; + + results[actionIndex] = _handleAction(action, params[actionIndex]); + } + + return abi.encode(results); + } + + /// @notice function to handle the parsing and execution of an action and its parameters + function _handleAction(uint256 action, bytes calldata params) internal virtual returns (bytes memory); + + /// @notice function that returns address considered executer of the actions + /// @dev The other context functions, _msgData and _msgValue, are not supported by this contract + /// In many contracts this will be the address that calls the initial entry point that calls `_executeActions` + /// `msg.sender` shouldnt be used, as this will be the v4 pool manager contract that calls `unlockCallback` + /// If using ReentrancyLock.sol, this function can return Locker.get() - locker of the contract + function _msgSender() internal view virtual returns (address); +} diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index 588d0e02..d5ff7883 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -3,20 +3,9 @@ pragma solidity ^0.8.24; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; -enum Actions { - MINT, - BURN, - INCREASE, - DECREASE, - // Any positive delta on a currency will be sent to specified address - CLOSE_CURRENCY -} - interface IPositionManager { - error MismatchedLengths(); error NotApproved(address caller); error DeadlinePassed(); - error UnsupportedAction(); error IncorrectPositionConfigForTokenId(uint256 tokenId); /// @notice Maps the ERC721 tokenId to a configId, which is a keccak256 hash of the position's pool key, and range (tickLower, tickUpper) diff --git a/src/libraries/Actions.sol b/src/libraries/Actions.sol index ca3e29fc..9b2fac6a 100644 --- a/src/libraries/Actions.sol +++ b/src/libraries/Actions.sol @@ -20,4 +20,8 @@ library Actions { // minting/burning 6909s to close deltas uint256 constant MINT_6909 = 0x20; uint256 constant BURN_6909 = 0x21; + + // mint + burn ERC721 position + uint256 constant MINT_POSITION = 0x22; + uint256 constant BURN_POSITION = 0x23; } diff --git a/test/position-managers/Execute.t.sol b/test/position-managers/Execute.t.sol index 718a04b3..96c8e7f9 100644 --- a/test/position-managers/Execute.t.sol +++ b/test/position-managers/Execute.t.sol @@ -15,9 +15,10 @@ import {Position} from "@uniswap/v4-core/src/libraries/Position.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; -import {IPositionManager, Actions} from "../../src/interfaces/IPositionManager.sol"; +import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; +import {Actions} from "../../src/libraries/Actions.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {Planner} from "../shared/Planner.sol"; @@ -85,8 +86,8 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.INCREASE, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); - planner = planner.add(Actions.INCREASE, abi.encode(tokenId, config, liquidityToAdd2, ZERO_BYTES)); + planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); + planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd2, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -107,8 +108,8 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT, abi.encode(config, initialLiquidity, address(this), ZERO_BYTES)); - planner = planner.add(Actions.INCREASE, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); + planner = planner.add(Actions.MINT_POSITION, abi.encode(config, initialLiquidity, address(this), ZERO_BYTES)); + planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); diff --git a/test/position-managers/Gas.t.sol b/test/position-managers/Gas.t.sol index 3e23d93f..aa2118be 100644 --- a/test/position-managers/Gas.t.sol +++ b/test/position-managers/Gas.t.sol @@ -16,7 +16,8 @@ import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; -import {IPositionManager, Actions} from "../../src/interfaces/IPositionManager.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 {IMulticall} from "../../src/interfaces/IMulticall.sol"; @@ -70,7 +71,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { function test_gas_mint() public { Planner.Plan memory planner = - Planner.init().add(Actions.MINT, abi.encode(config, 10_000 ether, address(this), ZERO_BYTES)); + Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(this), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_mint"); @@ -84,7 +85,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { vm.stopPrank(); // Mint to a diff config, diff user. Planner.Plan memory planner = - Planner.init().add(Actions.MINT, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); + Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); @@ -99,7 +100,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { vm.stopPrank(); // Mint to a diff config, diff user. Planner.Plan memory planner = - Planner.init().add(Actions.MINT, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); + Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); @@ -114,7 +115,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { vm.stopPrank(); // Mint to a diff config, diff user. Planner.Plan memory planner = - Planner.init().add(Actions.MINT, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); + Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); @@ -126,7 +127,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId() - 1; Planner.Plan memory planner = - Planner.init().add(Actions.INCREASE, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); + Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -166,7 +167,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { ); Planner.Plan memory planner = - Planner.init().add(Actions.INCREASE, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); + Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); @@ -207,7 +208,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { ); Planner.Plan memory planner = - Planner.init().add(Actions.INCREASE, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); + Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); @@ -221,7 +222,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId() - 1; Planner.Plan memory planner = - Planner.init().add(Actions.DECREASE, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); + Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -242,7 +243,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { }); Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT, abi.encode(config, 100e18, address(this), ZERO_BYTES)); + planner = planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); bytes memory actions = planner.finalize(config.poolKey); calls[1] = abi.encodeWithSelector(IPositionManager.modifyLiquidities.selector, actions, _deadline); @@ -259,7 +260,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { donateRouter.donate(config.poolKey, 0.2e18, 0.2e18, ZERO_BYTES); // Collect by calling decrease with 0. - Planner.Plan memory planner = Planner.init().add(Actions.DECREASE, abi.encode(tokenId, config, 0, ZERO_BYTES)); + Planner.Plan memory planner = + Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -271,7 +273,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); Planner.Plan memory planner = - Planner.init().add(Actions.MINT, abi.encode(config, 10_001 ether, address(alice), ZERO_BYTES)); + Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_001 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); @@ -288,7 +290,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId() - 1; Planner.Plan memory planner = - Planner.init().add(Actions.DECREASE, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); + Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -307,7 +309,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { // donate to create fee revenue donateRouter.donate(config.poolKey, 0.2e18, 0.2e18, ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.DECREASE, abi.encode(tokenId, config, 0, ZERO_BYTES)); + Planner.Plan memory planner = + Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -318,7 +321,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mint(config, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.BURN, abi.encode(tokenId, config, ZERO_BYTES)); + Planner.Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -330,7 +333,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); decreaseLiquidity(tokenId, config, 10_000 ether, ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.BURN, abi.encode(tokenId, config, ZERO_BYTES)); + Planner.Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); // There is no need to include CLOSE commands. bytes memory calls = planner.encode(); @@ -345,8 +348,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); Planner.Plan memory planner = - Planner.init().add(Actions.DECREASE, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); - planner = planner.add(Actions.BURN, abi.encode(tokenId, config, ZERO_BYTES)); + Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); + planner = planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); // We must include CLOSE commands. bytes memory calls = planner.finalize(config.poolKey); @@ -430,7 +433,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.BURN, abi.encode(tokenId, configNative, ZERO_BYTES)); + Planner.Plan memory planner = + Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); bytes memory calls = planner.finalize(configNative.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -442,7 +446,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); decreaseLiquidity(tokenId, configNative, 10_000 ether, ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.BURN, abi.encode(tokenId, configNative, ZERO_BYTES)); + Planner.Plan memory planner = + Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); // There is no need to include CLOSE commands. bytes memory calls = planner.encode(); @@ -457,8 +462,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); Planner.Plan memory planner = - Planner.init().add(Actions.DECREASE, abi.encode(tokenId, configNative, 10_000 ether, ZERO_BYTES)); - planner = planner.add(Actions.BURN, abi.encode(tokenId, configNative, ZERO_BYTES)); + Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, configNative, 10_000 ether, ZERO_BYTES)); + planner = planner.add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); // We must include CLOSE commands. bytes memory calls = planner.finalize(configNative.poolKey); diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index d38993a3..edbc308a 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -20,7 +20,8 @@ import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; -import {Actions, IPositionManager} from "../../src/interfaces/IPositionManager.sol"; +import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; +import {Actions} from "../../src/libraries/Actions.sol"; import {Planner} from "../shared/Planner.sol"; import {FeeMath} from "../shared/FeeMath.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; @@ -107,7 +108,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { // TODO: Can we make this easier to re-invest fees, so that you don't need to know the exact collect amount? Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.INCREASE, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); + planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.startPrank(alice); lpm.modifyLiquidities(calls, _deadline); diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index 926f124b..e44d7eea 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -24,7 +24,8 @@ import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {IERC721} from "@openzeppelin/contracts/interfaces/IERC721.sol"; -import {IPositionManager, Actions} from "../../src/interfaces/IPositionManager.sol"; +import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; +import {Actions} from "../../src/libraries/Actions.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; diff --git a/test/position-managers/PositionManager.multicall.t.sol b/test/position-managers/PositionManager.multicall.t.sol index 91085719..cfd53744 100644 --- a/test/position-managers/PositionManager.multicall.t.sol +++ b/test/position-managers/PositionManager.multicall.t.sol @@ -14,7 +14,8 @@ import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; -import {IPositionManager, Actions} from "../../src/interfaces/IPositionManager.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 {IMulticall} from "../../src/interfaces/IMulticall.sol"; @@ -54,7 +55,7 @@ contract PositionManagerMulticallTest is Test, PosmTestSetup, LiquidityFuzzers { }); Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT, abi.encode(config, 100e18, address(this), ZERO_BYTES)); + planner = planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); bytes memory actions = planner.finalize(config.poolKey); calls[1] = abi.encodeWithSelector(IPositionManager.modifyLiquidities.selector, actions, _deadline); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index cb72ee91..6ef399b1 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -17,9 +17,11 @@ import {Position} from "@uniswap/v4-core/src/libraries/Position.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; -import {IPositionManager, Actions} from "../../src/interfaces/IPositionManager.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 {BaseActionsRouterReturns} from "../../src/base/BaseActionsRouterReturns.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {Planner} from "../shared/Planner.sol"; @@ -49,12 +51,12 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { function test_modifyLiquidities_reverts_mismatchedLengths() public { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT, abi.encode("test")); - planner = planner.add(Actions.BURN, abi.encode("test")); + planner = planner.add(Actions.MINT_POSITION, abi.encode("test")); + planner = planner.add(Actions.BURN_POSITION, abi.encode("test")); bytes[] memory badParams = new bytes[](1); - vm.expectRevert(IPositionManager.MismatchedLengths.selector); + vm.expectRevert(BaseActionsRouterReturns.LengthMismatch.selector); lpm.modifyLiquidities(abi.encode(planner.actions, badParams), block.timestamp + 1); } diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index f29422eb..ef4e52a0 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -100,7 +100,7 @@ abstract contract LiquidityOperations is CommonBase { returns (bytes memory) { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT, abi.encode(config, liquidity, recipient, hookData)); + planner = planner.add(Actions.MINT_POSITION, abi.encode(config, liquidity, recipient, hookData)); return planner.finalize(config.poolKey); } @@ -112,7 +112,7 @@ abstract contract LiquidityOperations is CommonBase { bytes memory hookData ) internal pure returns (bytes memory) { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.INCREASE, abi.encode(tokenId, config, liquidityToAdd, hookData)); + planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, hookData)); return planner.finalize(config.poolKey); } @@ -123,7 +123,7 @@ abstract contract LiquidityOperations is CommonBase { bytes memory hookData ) internal pure returns (bytes memory) { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.DECREASE, abi.encode(tokenId, config, liquidityToRemove, hookData)); + planner = planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToRemove, hookData)); return planner.finalize(config.poolKey); } @@ -133,7 +133,7 @@ abstract contract LiquidityOperations is CommonBase { returns (bytes memory) { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.DECREASE, abi.encode(tokenId, config, 0, hookData)); + planner = planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, hookData)); return planner.finalize(config.poolKey); } @@ -143,7 +143,7 @@ abstract contract LiquidityOperations is CommonBase { returns (bytes memory) { Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.BURN, abi.encode(tokenId, config, hookData)); + planner = planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, hookData)); // Close needed on burn in case there is liquidity left in the position. return planner.finalize(config.poolKey); } diff --git a/test/shared/Planner.sol b/test/shared/Planner.sol index 8050c129..74a13461 100644 --- a/test/shared/Planner.sol +++ b/test/shared/Planner.sol @@ -3,22 +3,23 @@ pragma solidity ^0.8.20; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; -import {IPositionManager, Actions} from "../../src/interfaces/IPositionManager.sol"; +import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; +import {Actions} from "../../src/libraries/Actions.sol"; library Planner { using Planner for Plan; struct Plan { - Actions[] actions; + uint256[] actions; bytes[] params; } function init() internal pure returns (Plan memory plan) { - return Plan({actions: new Actions[](0), params: new bytes[](0)}); + return Plan({actions: new uint256[](0), params: new bytes[](0)}); } - function add(Plan memory plan, Actions action, bytes memory param) internal pure returns (Plan memory) { - Actions[] memory actions = new Actions[](plan.actions.length + 1); + function add(Plan memory plan, uint256 action, bytes memory param) internal pure returns (Plan memory) { + uint256[] memory actions = new uint256[](plan.actions.length + 1); bytes[] memory params = new bytes[](plan.params.length + 1); for (uint256 i; i < actions.length - 1; i++) { diff --git a/test/shared/fuzz/LiquidityFuzzers.sol b/test/shared/fuzz/LiquidityFuzzers.sol index a7a7d5d9..e4dac774 100644 --- a/test/shared/fuzz/LiquidityFuzzers.sol +++ b/test/shared/fuzz/LiquidityFuzzers.sol @@ -7,7 +7,8 @@ import {BalanceDelta, toBalanceDelta} from "@uniswap/v4-core/src/types/BalanceDe import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {Fuzzers} from "@uniswap/v4-core/src/test/Fuzzers.sol"; -import {IPositionManager, Actions} from "../../../src/interfaces/IPositionManager.sol"; +import {IPositionManager} from "../../../src/interfaces/IPositionManager.sol"; +import {Actions} from "../../../src/libraries/Actions.sol"; import {PositionConfig} from "../../../src/libraries/PositionConfig.sol"; import {Planner} from "../../shared/Planner.sol"; @@ -26,8 +27,9 @@ contract LiquidityFuzzers is Fuzzers { PositionConfig memory config = PositionConfig({poolKey: key, tickLower: params.tickLower, tickUpper: params.tickUpper}); - Planner.Plan memory planner = - Planner.init().add(Actions.MINT, abi.encode(config, uint256(params.liquidityDelta), recipient, hookData)); + Planner.Plan memory planner = Planner.init().add( + Actions.MINT_POSITION, abi.encode(config, uint256(params.liquidityDelta), recipient, hookData) + ); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, block.timestamp + 1); From 46f47b27119283ef8d329ce4d15ec580e65d7e18 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Sat, 27 Jul 2024 12:56:51 -0400 Subject: [PATCH 02/23] use one Planner file --- test/BaseActionsRouter.t.sol | 22 ++++---- test/position-managers/Execute.t.sol | 16 +++--- test/position-managers/Gas.t.sol | 52 +++++++++---------- .../position-managers/IncreaseLiquidity.t.sol | 8 +-- test/position-managers/NativeToken.t.sol | 4 +- .../PositionManager.multicall.t.sol | 8 +-- test/position-managers/PositionManager.t.sol | 10 ++-- test/shared/ActionsRouterPlanner.sol | 36 ------------- test/shared/LiquidityOperations.sol | 24 ++++----- test/shared/Planner.sol | 19 ++++--- test/shared/fuzz/LiquidityFuzzers.sol | 6 +-- 11 files changed, 84 insertions(+), 121 deletions(-) delete mode 100644 test/shared/ActionsRouterPlanner.sol diff --git a/test/BaseActionsRouter.t.sol b/test/BaseActionsRouter.t.sol index 8dafcb9d..7afd2e79 100644 --- a/test/BaseActionsRouter.t.sol +++ b/test/BaseActionsRouter.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.24; import {MockBaseActionsRouter} from "./mocks/MockBaseActionsRouter.sol"; -import {ActionsRouterPlanner, Plan} from "./shared/ActionsRouterPlanner.sol"; +import {Planner, Plan} from "./shared/Planner.sol"; import {Actions} from "../src/libraries/Actions.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {Test} from "forge-std/Test.sol"; @@ -10,7 +10,7 @@ import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol"; contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { - using ActionsRouterPlanner for Plan; + using Planner for Plan; MockBaseActionsRouter router; @@ -20,7 +20,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_swap_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.SWAP, ""); } @@ -35,7 +35,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_increaseLiquidity_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.INCREASE_LIQUIDITY, ""); } @@ -48,7 +48,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_decreaseLiquidity_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.DECREASE_LIQUIDITY, ""); } @@ -61,7 +61,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_donate_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.DONATE, ""); } @@ -74,7 +74,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_clear_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.CLEAR, ""); } @@ -87,7 +87,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_settle_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.SETTLE, ""); } @@ -100,7 +100,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_take_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.TAKE, ""); } @@ -113,7 +113,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_mint_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.MINT_6909, ""); } @@ -126,7 +126,7 @@ contract BaseActionsRouterTest is Test, Deployers, GasSnapshot { } function test_burn_suceeds() public { - Plan memory plan = ActionsRouterPlanner.init(); + Plan memory plan = Planner.init(); for (uint256 i = 0; i < 10; i++) { plan.add(Actions.BURN_6909, ""); } diff --git a/test/position-managers/Execute.t.sol b/test/position-managers/Execute.t.sol index 96c8e7f9..54d4f343 100644 --- a/test/position-managers/Execute.t.sol +++ b/test/position-managers/Execute.t.sol @@ -21,14 +21,14 @@ import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {Actions} from "../../src/libraries/Actions.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; -import {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; using PoolIdLibrary for PoolKey; - using Planner for Planner.Plan; + using Planner for Plan; using StateLibrary for IPoolManager; PoolId poolId; @@ -84,10 +84,10 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { mint(config, initialLiquidity, address(this), ZERO_BYTES); uint256 tokenId = lpm.nextTokenId() - 1; - Planner.Plan memory planner = Planner.init(); + Plan memory planner = Planner.init(); - planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); - planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd2, ZERO_BYTES)); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd2, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -106,10 +106,10 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); // assume that the .mint() produces tokenId=1, to be used in increaseLiquidity - Planner.Plan memory planner = Planner.init(); + Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT_POSITION, abi.encode(config, initialLiquidity, address(this), ZERO_BYTES)); - planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); + planner.add(Actions.MINT_POSITION, abi.encode(config, initialLiquidity, address(this), ZERO_BYTES)); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); diff --git a/test/position-managers/Gas.t.sol b/test/position-managers/Gas.t.sol index aa2118be..ef753869 100644 --- a/test/position-managers/Gas.t.sol +++ b/test/position-managers/Gas.t.sol @@ -21,14 +21,14 @@ import {Actions} from "../../src/libraries/Actions.sol"; import {PositionManager} from "../../src/PositionManager.sol"; import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {IMulticall} from "../../src/interfaces/IMulticall.sol"; -import {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; contract GasTest is Test, PosmTestSetup, GasSnapshot { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; using PoolIdLibrary for PoolKey; - using Planner for Planner.Plan; + using Planner for Plan; PoolId poolId; address alice; @@ -70,7 +70,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { } function test_gas_mint() public { - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(this), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -84,7 +84,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(bob_mint, 10_000 ether, address(bob), ZERO_BYTES); vm.stopPrank(); // Mint to a diff config, diff user. - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); @@ -99,7 +99,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(bob_mint, 10_000 ether, address(bob), ZERO_BYTES); vm.stopPrank(); // Mint to a diff config, diff user. - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); @@ -114,7 +114,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(bob_mint, 10_000 ether, address(bob), ZERO_BYTES); vm.stopPrank(); // Mint to a diff config, diff user. - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); @@ -126,7 +126,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); uint256 tokenId = lpm.nextTokenId() - 1; - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); @@ -166,7 +166,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { tokensOwedAlice ); - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); @@ -207,7 +207,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { halfTokensOwedAlice ); - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); @@ -221,7 +221,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); uint256 tokenId = lpm.nextTokenId() - 1; - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); @@ -242,8 +242,8 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { tickUpper: TickMath.maxUsableTick(key.tickSpacing) }); - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); bytes memory actions = planner.finalize(config.poolKey); calls[1] = abi.encodeWithSelector(IPositionManager.modifyLiquidities.selector, actions, _deadline); @@ -260,8 +260,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { donateRouter.donate(config.poolKey, 0.2e18, 0.2e18, ZERO_BYTES); // Collect by calling decrease with 0. - Planner.Plan memory planner = - Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); + Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -272,7 +271,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { function test_gas_sameRange_mint() public { mint(config, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_001 ether, address(alice), ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.prank(alice); @@ -289,7 +288,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); uint256 tokenId = lpm.nextTokenId() - 1; - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); @@ -309,8 +308,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { // donate to create fee revenue donateRouter.donate(config.poolKey, 0.2e18, 0.2e18, ZERO_BYTES); - Planner.Plan memory planner = - Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); + Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -321,7 +319,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mint(config, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); + Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -333,7 +331,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); decreaseLiquidity(tokenId, config, 10_000 ether, ZERO_BYTES); - Planner.Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); + Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); // There is no need to include CLOSE commands. bytes memory calls = planner.encode(); @@ -347,9 +345,9 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mint(config, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); - planner = planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); // We must include CLOSE commands. bytes memory calls = planner.finalize(config.poolKey); @@ -433,8 +431,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = - Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); + Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); bytes memory calls = planner.finalize(configNative.poolKey); lpm.modifyLiquidities(calls, _deadline); @@ -446,8 +443,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); decreaseLiquidity(tokenId, configNative, 10_000 ether, ZERO_BYTES); - Planner.Plan memory planner = - Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); + Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); // There is no need to include CLOSE commands. bytes memory calls = planner.encode(); @@ -461,9 +457,9 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { uint256 tokenId = lpm.nextTokenId(); mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); - Planner.Plan memory planner = + Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, configNative, 10_000 ether, ZERO_BYTES)); - planner = planner.add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); // We must include CLOSE commands. bytes memory calls = planner.finalize(configNative.poolKey); diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index edbc308a..da6d2739 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -22,7 +22,7 @@ import {PositionManager} from "../../src/PositionManager.sol"; import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {Actions} from "../../src/libraries/Actions.sol"; -import {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; import {FeeMath} from "../shared/FeeMath.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; @@ -30,7 +30,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; using PoolIdLibrary for PoolKey; - using Planner for Planner.Plan; + using Planner for Plan; using FeeMath for IPositionManager; PoolId poolId; @@ -107,8 +107,8 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { uint256 balance1BeforeAlice = currency1.balanceOf(alice); // TODO: Can we make this easier to re-invest fees, so that you don't need to know the exact collect amount? - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); + Plan memory planner = Planner.init(); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); bytes memory calls = planner.finalize(config.poolKey); vm.startPrank(alice); lpm.modifyLiquidities(calls, _deadline); diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index e44d7eea..90e22f56 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -30,14 +30,14 @@ import {PositionManager} from "../../src/PositionManager.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; -import {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; import {PositionConfig, PositionConfigLibrary} from "../../src/libraries/PositionConfig.sol"; contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; using PositionConfigLibrary for PositionConfig; - using Planner for Planner.Plan; + using Planner for Plan; using PoolIdLibrary for PoolKey; using StateLibrary for IPoolManager; using SafeCast for *; diff --git a/test/position-managers/PositionManager.multicall.t.sol b/test/position-managers/PositionManager.multicall.t.sol index cfd53744..1aaef5be 100644 --- a/test/position-managers/PositionManager.multicall.t.sol +++ b/test/position-managers/PositionManager.multicall.t.sol @@ -20,13 +20,13 @@ import {PositionManager} from "../../src/PositionManager.sol"; import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {IMulticall} from "../../src/interfaces/IMulticall.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; -import {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; contract PositionManagerMulticallTest is Test, PosmTestSetup, LiquidityFuzzers { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; - using Planner for Planner.Plan; + using Planner for Plan; PoolId poolId; address alice = makeAddr("ALICE"); @@ -54,8 +54,8 @@ contract PositionManagerMulticallTest is Test, PosmTestSetup, LiquidityFuzzers { tickUpper: TickMath.maxUsableTick(key.tickSpacing) }); - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); bytes memory actions = planner.finalize(config.poolKey); calls[1] = abi.encodeWithSelector(IPositionManager.modifyLiquidities.selector, actions, _deadline); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index 6ef399b1..ed582137 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -24,7 +24,7 @@ import {PositionConfig} from "../../src/libraries/PositionConfig.sol"; import {BaseActionsRouterReturns} from "../../src/base/BaseActionsRouterReturns.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; -import {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; import {PosmTestSetup} from "../shared/PosmTestSetup.sol"; import {ReentrantToken} from "../mocks/ReentrantToken.sol"; import {ReentrancyLock} from "../../src/base/ReentrancyLock.sol"; @@ -32,7 +32,7 @@ import {ReentrancyLock} from "../../src/base/ReentrancyLock.sol"; contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { using FixedPointMathLib for uint256; using CurrencyLibrary for Currency; - using Planner for Planner.Plan; + using Planner for Plan; using PoolIdLibrary for PoolKey; using StateLibrary for IPoolManager; @@ -50,9 +50,9 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { } function test_modifyLiquidities_reverts_mismatchedLengths() public { - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT_POSITION, abi.encode("test")); - planner = planner.add(Actions.BURN_POSITION, abi.encode("test")); + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode("test")); + planner.add(Actions.BURN_POSITION, abi.encode("test")); bytes[] memory badParams = new bytes[](1); diff --git a/test/shared/ActionsRouterPlanner.sol b/test/shared/ActionsRouterPlanner.sol deleted file mode 100644 index 8ea06662..00000000 --- a/test/shared/ActionsRouterPlanner.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.24; - -struct Plan { - uint256[] actions; - bytes[] params; -} - -library ActionsRouterPlanner { - function init() internal pure returns (Plan memory plan) { - return Plan({actions: new uint256[](0), params: new bytes[](0)}); - } - - function add(Plan memory plan, uint256 action, bytes memory param) internal pure returns (Plan memory) { - uint256[] memory actions = new uint256[](plan.actions.length + 1); - bytes[] memory params = new bytes[](plan.params.length + 1); - - for (uint256 i; i < actions.length - 1; i++) { - // Copy from plan. - actions[i] = plan.actions[i]; - params[i] = plan.params[i]; - } - - actions[actions.length - 1] = action; - params[params.length - 1] = param; - - plan.actions = actions; - plan.params = params; - - return plan; - } - - function encode(Plan memory plan) internal pure returns (bytes memory) { - return abi.encode(plan.actions, plan.params); - } -} diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index ef4e52a0..d76aa4a7 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -11,10 +11,10 @@ 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 {Planner} from "../shared/Planner.sol"; +import {Planner, Plan} from "../shared/Planner.sol"; abstract contract LiquidityOperations is CommonBase { - using Planner for Planner.Plan; + using Planner for Plan; using SafeCast for *; PositionManager lpm; @@ -99,8 +99,8 @@ abstract contract LiquidityOperations is CommonBase { pure returns (bytes memory) { - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.MINT_POSITION, abi.encode(config, liquidity, recipient, hookData)); + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(config, liquidity, recipient, hookData)); return planner.finalize(config.poolKey); } @@ -111,8 +111,8 @@ abstract contract LiquidityOperations is CommonBase { uint256 liquidityToAdd, bytes memory hookData ) internal pure returns (bytes memory) { - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, hookData)); + Plan memory planner = Planner.init(); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, hookData)); return planner.finalize(config.poolKey); } @@ -122,8 +122,8 @@ abstract contract LiquidityOperations is CommonBase { uint256 liquidityToRemove, bytes memory hookData ) internal pure returns (bytes memory) { - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToRemove, hookData)); + Plan memory planner = Planner.init(); + planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToRemove, hookData)); return planner.finalize(config.poolKey); } @@ -132,8 +132,8 @@ abstract contract LiquidityOperations is CommonBase { pure returns (bytes memory) { - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, hookData)); + Plan memory planner = Planner.init(); + planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, hookData)); return planner.finalize(config.poolKey); } @@ -142,8 +142,8 @@ abstract contract LiquidityOperations is CommonBase { pure returns (bytes memory) { - Planner.Plan memory planner = Planner.init(); - planner = planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, hookData)); + Plan memory planner = Planner.init(); + planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, hookData)); // Close needed on burn in case there is liquidity left in the position. return planner.finalize(config.poolKey); } diff --git a/test/shared/Planner.sol b/test/shared/Planner.sol index 74a13461..8475f831 100644 --- a/test/shared/Planner.sol +++ b/test/shared/Planner.sol @@ -6,14 +6,14 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {IPositionManager} from "../../src/interfaces/IPositionManager.sol"; import {Actions} from "../../src/libraries/Actions.sol"; +struct Plan { + uint256[] actions; + bytes[] params; +} + library Planner { using Planner for Plan; - struct Plan { - uint256[] actions; - bytes[] params; - } - function init() internal pure returns (Plan memory plan) { return Plan({actions: new uint256[](0), params: new bytes[](0)}); } @@ -31,12 +31,15 @@ library Planner { actions[actions.length - 1] = action; params[params.length - 1] = param; - return Plan({actions: actions, params: params}); + plan.actions = actions; + plan.params = params; + + return plan; } function finalize(Plan memory plan, PoolKey memory poolKey) internal pure returns (bytes memory) { - plan = plan.add(Actions.CLOSE_CURRENCY, abi.encode(poolKey.currency0)); - plan = plan.add(Actions.CLOSE_CURRENCY, abi.encode(poolKey.currency1)); + plan.add(Actions.CLOSE_CURRENCY, abi.encode(poolKey.currency0)); + plan.add(Actions.CLOSE_CURRENCY, abi.encode(poolKey.currency1)); return plan.encode(); } diff --git a/test/shared/fuzz/LiquidityFuzzers.sol b/test/shared/fuzz/LiquidityFuzzers.sol index e4dac774..bff8edde 100644 --- a/test/shared/fuzz/LiquidityFuzzers.sol +++ b/test/shared/fuzz/LiquidityFuzzers.sol @@ -10,10 +10,10 @@ 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} from "../../shared/Planner.sol"; +import {Planner, Plan} from "../../shared/Planner.sol"; contract LiquidityFuzzers is Fuzzers { - using Planner for Planner.Plan; + using Planner for Plan; function addFuzzyLiquidity( IPositionManager lpm, @@ -27,7 +27,7 @@ contract LiquidityFuzzers is Fuzzers { PositionConfig memory config = PositionConfig({poolKey: key, tickLower: params.tickLower, tickUpper: params.tickUpper}); - Planner.Plan memory planner = Planner.init().add( + Plan memory planner = Planner.init().add( Actions.MINT_POSITION, abi.encode(config, uint256(params.liquidityDelta), recipient, hookData) ); From b198c305c3044f5d2cabb1ad32d9e05b37a2c33f Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Sat, 27 Jul 2024 13:04:13 -0400 Subject: [PATCH 03/23] msgSender --- src/PositionManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PositionManager.sol b/src/PositionManager.sol index bb701bc6..2a65f95d 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -110,7 +110,7 @@ contract PositionManager is (uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes memory hookData) = abi.decode(params, (uint256, PositionConfig, uint256, bytes)); - if (!_isApprovedOrOwner(_getLocker(), tokenId)) revert NotApproved(_getLocker()); + if (!_isApprovedOrOwner(_msgSender(), tokenId)) revert NotApproved(_msgSender()); if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); // Note: the tokenId is used as the salt. @@ -149,7 +149,7 @@ contract PositionManager is int256 currencyDelta = poolManager.currencyDelta(address(this), currency); // the locker is the payer or receiver - address caller = _getLocker(); + address caller = _msgSender(); if (currencyDelta < 0) { _settle(currency, caller, uint256(-currencyDelta)); @@ -168,7 +168,7 @@ contract PositionManager is (uint256 tokenId, PositionConfig memory config, bytes memory hookData) = abi.decode(params, (uint256, PositionConfig, bytes)); - if (!_isApprovedOrOwner(_getLocker(), tokenId)) revert NotApproved(_getLocker()); + if (!_isApprovedOrOwner(_msgSender(), tokenId)) revert NotApproved(_msgSender()); if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); uint256 liquidity = uint256(_getPositionLiquidity(config, tokenId)); From 3482b239a456df7a2a06677102d6bd503d93fcc8 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Sat, 27 Jul 2024 16:22:30 -0400 Subject: [PATCH 04/23] add transfer --- ...sitionManager_increaseLiquidity_erc20.snap | 2 +- ...itionManager_increaseLiquidity_native.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...anager_mint_warmedPool_differentRange.snap | 2 +- ...tionManager_multicall_initialize_mint.snap | 2 +- src/PositionManager.sol | 43 +++++++++++++++++-- src/interfaces/IPositionManager.sol | 3 ++ src/libraries/Actions.sol | 3 ++ .../position-managers/IncreaseLiquidity.t.sol | 28 ++++++++++++ 14 files changed, 84 insertions(+), 13 deletions(-) diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index 378102d1..5afd30aa 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -148641 \ No newline at end of file +148697 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index 19228ded..47315a1b 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -133851 \ No newline at end of file +133879 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index 37f10e0d..aa48f77b 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -368720 \ No newline at end of file +368776 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 30e2aca0..70db2026 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -336830 \ No newline at end of file +336858 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index e2d6bd57..470829f3 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -343768 \ No newline at end of file +343796 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index c84f0131..e633870e 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -311402 \ No newline at end of file +311458 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index ff7f6612..0c7a3cc5 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -312044 \ No newline at end of file +312100 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index d1a17915..5665f1b7 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -237626 \ No newline at end of file +237682 \ 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 87917a85..a9ceafa3 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -317420 \ No newline at end of file +317476 \ 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 9ed80c5c..8a1a7a16 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -413210 \ No newline at end of file +413266 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 2a65f95d..f9f1f8b5 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -47,6 +47,8 @@ contract PositionManager is /// @inheritdoc IPositionManager mapping(uint256 tokenId => bytes32 configId) public positionConfigs; + uint256 public constant FULL_DELTA = type(uint256).max; + constructor(IPoolManager _poolManager) BaseActionsRouterReturns(_poolManager) ERC721Permit("Uniswap V4 Positions NFT", "UNI-V4-POSM", "1") @@ -81,6 +83,8 @@ contract PositionManager is return _close(params); } else if (action == Actions.BURN_POSITION) { return _burn(params); + } else if (action == Actions.SETTLE_WITH_BALANCE) { + return _settleWithBalance(params); } else { revert UnsupportedAction(action); } @@ -162,6 +166,20 @@ contract PositionManager is return abi.encode(currencyDelta); } + /// @param params is an encoding of Currency, uint256 amount + /// @dev if amount == FULL_DELTA, it settles the full negative delta + /// @dev uses this addresses balance to settle a negative delta + /// @dev Should not be called for NATIVE settling bc does not sweep. + function _settleWithBalance(bytes memory params) internal returns (bytes memory) { + (Currency currency, uint256 amount) = abi.decode(params, (Currency, uint256)); + + amount = amount == FULL_DELTA ? _getFullSettleAmount(currency) : amount; + + // set the payer to this address, performs a transfer. + _settle(currency, address(this), amount); + return abi.encode(amount); + } + /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, bytes hookData /// @dev this is overloaded with ERC721Permit._burn function _burn(bytes memory params) internal returns (bytes memory) { @@ -218,8 +236,27 @@ contract PositionManager is } // implementation of abstract function DeltaResolver._pay - function _pay(Currency token, address payer, uint256 amount) internal override { - // TODO this should use Permit2 - ERC20(Currency.unwrap(token)).safeTransferFrom(payer, address(poolManager), amount); + function _pay(Currency currency, address payer, uint256 amount) internal override { + if (payer == address(this)) { + // TODO: This transfer no eth check. This is guaranteed to not be eth. + currency.transfer(address(poolManager), amount); + } else { + // TODO this should use Permit2 + ERC20(Currency.unwrap(currency)).safeTransferFrom(payer, address(poolManager), amount); + } + } + + function _getFullSettleAmount(Currency currency) private view returns (uint256 amount) { + int256 _amount = poolManager.currencyDelta(address(this), currency); + // If the amount is positive, it should be taken not settled for. + if (_amount > 0) revert IncorrectUseOfSettle(); + amount = uint256(-_amount); + } + + function _getFullTakeAmount(Currency currency) private view returns (uint256 amount) { + int256 _amount = poolManager.currencyDelta(address(this), currency); + // If the amount is negative, it should be settled not taken. + if (_amount < 0) revert IncorrectUseOfTake(); + amount = uint256(_amount); } } diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index d5ff7883..958eb8fb 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -6,6 +6,9 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; interface IPositionManager { error NotApproved(address caller); error DeadlinePassed(); + error NothingToSettle(); + error IncorrectUseOfTake(); + error IncorrectUseOfSettle(); error IncorrectPositionConfigForTokenId(uint256 tokenId); /// @notice Maps the ERC721 tokenId to a configId, which is a keccak256 hash of the position's pool key, and range (tickLower, tickUpper) diff --git a/src/libraries/Actions.sol b/src/libraries/Actions.sol index 9b2fac6a..69e30029 100644 --- a/src/libraries/Actions.sol +++ b/src/libraries/Actions.sol @@ -24,4 +24,7 @@ library Actions { // mint + burn ERC721 position uint256 constant MINT_POSITION = 0x22; uint256 constant BURN_POSITION = 0x23; + + // settle using the balance contract + uint256 constant SETTLE_WITH_BALANCE = 0x24; } diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index da6d2739..308de483 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -335,4 +335,32 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { ); } } + + function test_mint_settleWithBalance() public { + uint256 liquidityAlice = 3_000e18; + + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); + + assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 0); + assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 0); + + currency0.transfer(address(lpm), 100e18); + currency1.transfer(address(lpm), 100e18); + + assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 100e18); + assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 100e18); + + bytes memory calls = planner.encode(); + + vm.prank(alice); + bytes[] memory results = lpm.modifyLiquidities(calls, _deadline); + uint256 amount0 = abi.decode(results[1], (uint256)); + uint256 amount1 = abi.decode(results[2], (uint256)); + + assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 100e18 - amount0); + assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 100e18 - amount1); + } } From 2cee496494766a13fc665bd39ed95b42e569e161 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Sat, 27 Jul 2024 16:35:50 -0400 Subject: [PATCH 05/23] add transfer test --- src/PositionManager.sol | 9 ++++++++ src/libraries/Actions.sol | 1 + .../position-managers/IncreaseLiquidity.t.sol | 21 +++++++++++++------ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/PositionManager.sol b/src/PositionManager.sol index f9f1f8b5..f419973c 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -85,6 +85,8 @@ contract PositionManager is return _burn(params); } else if (action == Actions.SETTLE_WITH_BALANCE) { return _settleWithBalance(params); + } else if (action == Actions.SWEEP_ERC20_TO) { + _sweepERC20To(params); } else { revert UnsupportedAction(action); } @@ -235,6 +237,13 @@ contract PositionManager is if (nativeBalance > 0) recipient.safeTransferETH(nativeBalance); } + /// @param params an encoding of Currency, address + function _sweepERC20To(bytes calldata params) internal { + (Currency currency, address to) = abi.decode(params, (Currency, address)); + uint256 tokenBalance = ERC20(Currency.unwrap(currency)).balanceOf(address(this)); + if (tokenBalance > 0) currency.transfer(to, tokenBalance); + } + // implementation of abstract function DeltaResolver._pay function _pay(Currency currency, address payer, uint256 amount) internal override { if (payer == address(this)) { diff --git a/src/libraries/Actions.sol b/src/libraries/Actions.sol index 69e30029..cf59d340 100644 --- a/src/libraries/Actions.sol +++ b/src/libraries/Actions.sol @@ -27,4 +27,5 @@ library Actions { // settle using the balance contract uint256 constant SETTLE_WITH_BALANCE = 0x24; + uint256 constant SWEEP_ERC20_TO = 0x25; } diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 308de483..5cce961c 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -343,15 +343,20 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); + planner.add(Actions.SWEEP_ERC20_TO, abi.encode(currency0, address(this))); + planner.add(Actions.SWEEP_ERC20_TO, abi.encode(currency1, address(this))); - assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 0); - assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 0); + uint256 balanceBefore0 = currency0.balanceOf(address(this)); + uint256 balanceBefore1 = currency1.balanceOf(address(this)); + + assertEq(currency0.balanceOf(address(lpm)), 0); + assertEq(currency0.balanceOf(address(lpm)), 0); currency0.transfer(address(lpm), 100e18); currency1.transfer(address(lpm), 100e18); - assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 100e18); - assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 100e18); + assertEq(currency0.balanceOf(address(lpm)), 100e18); + assertEq(currency0.balanceOf(address(lpm)), 100e18); bytes memory calls = planner.encode(); @@ -360,7 +365,11 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { uint256 amount0 = abi.decode(results[1], (uint256)); uint256 amount1 = abi.decode(results[2], (uint256)); - assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 100e18 - amount0); - assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 100e18 - amount1); + // The balances were swept back to this address. + assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 0); + assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 0); + + assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amount0); + assertEq(currency1.balanceOf(address(this)), balanceBefore0 - amount0); } } From 494f7d635d83d681f2331862673eedc440340ed7 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 29 Jul 2024 17:34:19 -0400 Subject: [PATCH 06/23] use delta saving hook to get deltas --- .../PositionManager_burn_empty.snap | 2 +- .../PositionManager_burn_empty_native.snap | 2 +- .../PositionManager_burn_nonEmpty.snap | 2 +- .../PositionManager_burn_nonEmpty_native.snap | 2 +- .forge-snapshots/PositionManager_collect.snap | 2 +- .../PositionManager_collect_native.snap | 2 +- .../PositionManager_collect_sameRange.snap | 2 +- .../PositionManager_decreaseLiquidity.snap | 2 +- ...itionManager_decreaseLiquidity_native.snap | 2 +- .../PositionManager_decrease_burnEmpty.snap | 2 +- ...tionManager_decrease_burnEmpty_native.snap | 2 +- ...nager_decrease_sameRange_allLiquidity.snap | 2 +- ...sitionManager_increaseLiquidity_erc20.snap | 2 +- ...itionManager_increaseLiquidity_native.snap | 2 +- ...crease_autocompoundExactUnclaimedFees.snap | 2 +- ...increase_autocompoundExcessFeesCredit.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...anager_mint_warmedPool_differentRange.snap | 2 +- test/position-managers/Execute.t.sol | 5 ++- test/position-managers/FeeCollection.t.sol | 17 ++++--- test/position-managers/Gas.t.sol | 7 ++- .../position-managers/IncreaseLiquidity.t.sol | 5 ++- test/position-managers/NativeToken.t.sol | 39 +++++++++------- test/position-managers/PositionManager.t.sol | 23 ++++++---- test/shared/HookSavesDelta.sol | 43 ++++++++++++++++++ test/shared/LiquidityOperations.sol | 44 +++++++++++-------- test/shared/PosmTestSetup.sol | 9 ++++ 32 files changed, 164 insertions(+), 74 deletions(-) create mode 100644 test/shared/HookSavesDelta.sol diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index ae544d1e..1b58562d 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -49187 \ No newline at end of file +49196 \ 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 9a8f81bd..e355943e 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -49004 \ No newline at end of file +49014 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty.snap b/.forge-snapshots/PositionManager_burn_nonEmpty.snap index 4ea5699e..67498f64 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty.snap @@ -1 +1 @@ -134167 \ No newline at end of file +159808 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap index edc67bec..507f2d5c 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap @@ -1 +1 @@ -127088 \ No newline at end of file +152729 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect.snap b/.forge-snapshots/PositionManager_collect.snap index 23e7811d..633f7fdc 100644 --- a/.forge-snapshots/PositionManager_collect.snap +++ b/.forge-snapshots/PositionManager_collect.snap @@ -1 +1 @@ -156257 \ No newline at end of file +188308 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index eac09c8d..3ec22d6a 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -147409 \ No newline at end of file +179460 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index 23e7811d..633f7fdc 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -156257 \ No newline at end of file +188308 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity.snap b/.forge-snapshots/PositionManager_decreaseLiquidity.snap index bfdc5971..d522203c 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity.snap @@ -1 +1 @@ -121800 \ No newline at end of file +153851 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index f2fa3ab8..17f43208 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -113402 \ No newline at end of file +145003 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index 23a0e2f8..4ee229e8 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -140263 \ No newline at end of file +165913 \ 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 38f35b9d..5f4e2340 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -133002 \ No newline at end of file +158652 \ 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 24f47000..37a2aae5 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -134516 \ No newline at end of file +166567 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index bf03d8fc..e7e9dc6e 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -157772 \ No newline at end of file +189790 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index c913f4db..01886ef2 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -139655 \ No newline at end of file +171673 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index 069affb6..bf0cfe74 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -140478 \ No newline at end of file +152596 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index cdd8307e..94c0a7b3 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -176634 \ No newline at end of file +208652 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index 44c4fb5c..21fe5a19 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -377851 \ No newline at end of file +426969 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 79b8a9f0..0aa4da2d 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -342634 \ No newline at end of file +391752 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index 613294fc..387c5aee 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -349572 \ No newline at end of file +398690 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index add09152..be487fc8 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -320533 \ No newline at end of file +352551 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index 2292a6e4..e5e6cc84 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -321175 \ No newline at end of file +353193 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index fc4122f6..22a69dac 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -246757 \ No newline at end of file +278775 \ 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 07a7f950..c2a73544 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -326551 \ No newline at end of file +358569 \ No newline at end of file diff --git a/test/position-managers/Execute.t.sol b/test/position-managers/Execute.t.sol index 54d4f343..7b38d73d 100644 --- a/test/position-managers/Execute.t.sol +++ b/test/position-managers/Execute.t.sol @@ -41,7 +41,10 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + // deploy this since all functions used in LiquidityOperations require the snapshotting to work + deployPosmHookSavesDelta(); + + (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); // Requires currency0 and currency1 to be set in base Deployers contract. deployAndApprovePosm(manager); diff --git a/test/position-managers/FeeCollection.t.sol b/test/position-managers/FeeCollection.t.sol index 39e85b74..472cd91d 100644 --- a/test/position-managers/FeeCollection.t.sol +++ b/test/position-managers/FeeCollection.t.sol @@ -37,7 +37,10 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + // This is needed to receive return deltas from modifyLiquidity calls. + deployPosmHookSavesDelta(); + + (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); FEE_WAD = uint256(key.fee).mulDivDown(FixedPointMathLib.WAD, 1_000_000); // Requires currency0 and currency1 to be set in base Deployers contract. @@ -71,7 +74,8 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0Before = currency0.balanceOfSelf(); uint256 balance1Before = currency1.balanceOfSelf(); - BalanceDelta delta = collect(tokenId, config, ZERO_BYTES); + collect(tokenId, config, ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); assertEq(uint256(int256(delta.amount1())), uint256(int256(expectedFees.amount1()))); assertEq(uint256(int256(delta.amount0())), uint256(int256(expectedFees.amount0()))); @@ -114,8 +118,9 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0AliceBefore = currency0.balanceOf(alice); uint256 balance1AliceBefore = currency1.balanceOf(alice); vm.startPrank(alice); - BalanceDelta delta = collect(tokenIdAlice, config, ZERO_BYTES); + collect(tokenIdAlice, config, ZERO_BYTES); vm.stopPrank(); + BalanceDelta delta = snapLastDelta(); uint256 balance0AliceAfter = currency0.balanceOf(alice); uint256 balance1AliceAfter = currency1.balanceOf(alice); @@ -127,8 +132,9 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0BobBefore = currency0.balanceOf(bob); uint256 balance1BobBefore = currency1.balanceOf(bob); vm.startPrank(bob); - delta = collect(tokenIdBob, config, ZERO_BYTES); + collect(tokenIdBob, config, ZERO_BYTES); vm.stopPrank(); + delta = snapLastDelta(); uint256 balance0BobAfter = currency0.balanceOf(bob); uint256 balance1BobAfter = currency1.balanceOf(bob); @@ -158,8 +164,9 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenIdBob = lpm.nextTokenId(); vm.startPrank(bob); - BalanceDelta lpDeltaBob = mint(config, liquidityBob, bob, ZERO_BYTES); + mint(config, liquidityBob, bob, ZERO_BYTES); vm.stopPrank(); + BalanceDelta lpDeltaBob = snapLastDelta(); // swap to create fees uint256 swapAmount = 0.001e18; diff --git a/test/position-managers/Gas.t.sol b/test/position-managers/Gas.t.sol index ef753869..870703e1 100644 --- a/test/position-managers/Gas.t.sol +++ b/test/position-managers/Gas.t.sol @@ -49,8 +49,11 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); - (nativeKey,) = initPool(CurrencyLibrary.NATIVE, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + // This is needed to receive return deltas from modifyLiquidity calls. + deployPosmHookSavesDelta(); + + (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (nativeKey,) = initPool(CurrencyLibrary.NATIVE, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); FEE_WAD = uint256(key.fee).mulDivDown(FixedPointMathLib.WAD, 1_000_000); // Requires currency0 and currency1 to be set in base Deployers contract. diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index da6d2739..554f48dc 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -49,7 +49,10 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + // This is needed to receive return deltas from modifyLiquidity calls. + deployPosmHookSavesDelta(); + + (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); FEE_WAD = uint256(key.fee).mulDivDown(FixedPointMathLib.WAD, 1_000_000); // Requires currency0 and currency1 to be set in base Deployers contract. diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index ea81fc08..54ff1b2b 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -48,8 +48,11 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); + // This is needed to receive return deltas from modifyLiquidity calls. + deployPosmHookSavesDelta(); + currency0 = CurrencyLibrary.NATIVE; - (nativeKey, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (nativeKey, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); deployPosm(manager); // currency0 is the native token so only execute approvals for currency1. @@ -80,8 +83,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { liquidityToAdd.toUint128() ); // add extra wei because modifyLiquidities may be rounding up, LiquidityAmounts is imprecise? - bytes[] memory result = lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); - BalanceDelta delta = abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); + BalanceDelta delta = snapLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); @@ -116,8 +119,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { ); // Mint with excess native tokens - bytes[] memory result = lpm.modifyLiquidities{value: amount0 * 2 + 1}(calls, _deadline); - BalanceDelta delta = abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities{value: amount0 * 2 + 1}(calls, _deadline); + BalanceDelta delta = snapLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); @@ -154,10 +157,13 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0BeforeBurn = currency0.balanceOfSelf(); uint256 balance1BeforeBurn = currency1.balanceOfSelf(); - BalanceDelta deltaDecrease = decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); - BalanceDelta deltaBurn = burn(tokenId, config, ZERO_BYTES); - assertEq(deltaBurn.amount0(), 0); - assertEq(deltaBurn.amount1(), 0); + decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); + BalanceDelta deltaDecrease = snapLastDelta(); + + uint256 deltasSnapsLength = hook.getDeltasLength(); + burn(tokenId, config, ZERO_BYTES); + // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. + assertEq(deltasSnapsLength, hook.getDeltasLength()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); assertEq(liquidity, 0); @@ -204,7 +210,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0BeforeBurn = currency0.balanceOfSelf(); uint256 balance1BeforeBurn = currency1.balanceOfSelf(); - BalanceDelta deltaBurn = burn(tokenId, config, ZERO_BYTES); + burn(tokenId, config, ZERO_BYTES); + BalanceDelta deltaBurn = snapLastDelta(); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); assertEq(liquidity, 0); @@ -254,7 +261,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, ZERO_BYTES); // double the liquidity bytes[] memory result = lpm.modifyLiquidities{value: amount0 + 1 wei}(calls, _deadline); // TODO: off by one wei - BalanceDelta delta = abi.decode(result[0], (BalanceDelta)); + BalanceDelta delta = snapLastDelta(); // verify position liquidity increased bytes32 positionId = @@ -295,8 +302,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { ); bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, ZERO_BYTES); // double the liquidity - bytes[] memory result = lpm.modifyLiquidities{value: amount0 * 2}(calls, _deadline); // overpay on increase liquidity - BalanceDelta delta = abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities{value: amount0 * 2}(calls, _deadline); // overpay on increase liquidity + BalanceDelta delta = snapLastDelta(); // verify position liquidity increased bytes32 positionId = @@ -335,7 +342,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { TickMath.getSqrtPriceAtTick(params.tickUpper), uint128(decreaseLiquidityDelta) ); - BalanceDelta delta = decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); + decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); @@ -366,7 +374,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0Before = address(this).balance; uint256 balance1Before = currency1.balanceOfSelf(); - BalanceDelta delta = collect(tokenId, config, ZERO_BYTES); + collect(tokenId, config, ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); assertApproxEqAbs(currency0.balanceOfSelf() - balance0Before, feeRevenue0, 1 wei); // TODO: fuzzer off by 1 wei assertEq(currency0.balanceOfSelf() - balance0Before, uint128(delta.amount0())); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index c392b2fd..747525dc 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -44,7 +44,10 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + // This is needed to receive return deltas from modifyLiquidity calls. + deployPosmHookSavesDelta(); + + (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); // Requires currency0 and currency1 to be set in base Deployers contract. deployAndApprovePosm(manager); @@ -192,11 +195,12 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0BeforeBurn = currency0.balanceOfSelf(); uint256 balance1BeforeBurn = currency1.balanceOfSelf(); - BalanceDelta deltaDecrease = decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); - // No decrease will happen on the burn call so the delta will be 0. - (BalanceDelta delta) = burn(tokenId, config, ZERO_BYTES); - assertEq(delta.amount0(), 0); - assertEq(delta.amount1(), 0); + decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); + BalanceDelta deltaDecrease = snapLastDelta(); + uint256 deltasSnapsLength = hook.getDeltasLength(); + // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. + burn(tokenId, config, ZERO_BYTES); + assertEq(deltasSnapsLength, hook.getDeltasLength()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); @@ -245,7 +249,9 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0BeforeBurn = currency0.balanceOfSelf(); uint256 balance1BeforeBurn = currency1.balanceOfSelf(); - BalanceDelta deltaBurn = burn(tokenId, config, ZERO_BYTES); + burn(tokenId, config, ZERO_BYTES); + BalanceDelta deltaBurn = snapLastDelta(); + assertEq(uint256(int256(deltaBurn.amount0())), amount0); assertEq(uint256(int256(deltaBurn.amount1())), amount1); @@ -306,7 +312,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0Before = currency0.balanceOfSelf(); uint256 balance1Before = currency1.balanceOfSelf(); - BalanceDelta delta = decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); + decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); diff --git a/test/shared/HookSavesDelta.sol b/test/shared/HookSavesDelta.sol new file mode 100644 index 00000000..17c60cc8 --- /dev/null +++ b/test/shared/HookSavesDelta.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; +import {BalanceDelta, BalanceDeltaLibrary} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; + +import {BaseTestHooks} from "@uniswap/v4-core/src/test/BaseTestHooks.sol"; + +/// @notice This contract is NOT a production use contract. It is meant to be used in testing to verify the delta amounts against changes in a user's balance. +contract HookSavesDelta is BaseTestHooks { + BalanceDelta[] public deltas; + + function afterAddLiquidity( + address, /* sender **/ + PoolKey calldata, /* key **/ + IPoolManager.ModifyLiquidityParams calldata, /* params **/ + BalanceDelta delta, + bytes calldata /* hookData **/ + ) external override returns (bytes4, BalanceDelta) { + _storeDelta(delta); + return (this.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA); + } + + function afterRemoveLiquidity( + address, /* sender **/ + PoolKey calldata, /* key **/ + IPoolManager.ModifyLiquidityParams calldata, /* params **/ + BalanceDelta delta, + bytes calldata /* hookData **/ + ) external override returns (bytes4, BalanceDelta) { + _storeDelta(delta); + return (this.afterRemoveLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA); + } + + function _storeDelta(BalanceDelta delta) internal { + deltas.push(delta); + } + + function getDeltasLength() external view returns (uint256) { + return deltas.length; + } +} diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index d76aa4a7..9558726c 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -12,6 +12,7 @@ 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 {Planner, Plan} from "../shared/Planner.sol"; +import {HookSavesDelta} from "./HookSavesDelta.sol"; abstract contract LiquidityOperations is CommonBase { using Planner for Plan; @@ -19,15 +20,17 @@ abstract contract LiquidityOperations is CommonBase { PositionManager lpm; + HookSavesDelta hook; + uint256 _deadline = block.timestamp + 1; function mint(PositionConfig memory config, uint256 liquidity, address recipient, bytes memory hookData) internal - returns (BalanceDelta) + returns (BalanceDelta delta) { bytes memory calls = getMintEncoded(config, liquidity, recipient, hookData); - bytes[] memory result = lpm.modifyLiquidities(calls, _deadline); - return abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities(calls, _deadline); + delta = hook.deltas(0); } function mintWithNative( @@ -36,7 +39,7 @@ abstract contract LiquidityOperations is CommonBase { uint256 liquidity, address recipient, bytes memory hookData - ) internal returns (BalanceDelta) { + ) internal returns (BalanceDelta delta) { // determine the amount of ETH to send on-mint (uint256 amount0,) = LiquidityAmounts.getAmountsForLiquidity( sqrtPriceX96, @@ -46,9 +49,8 @@ abstract contract LiquidityOperations is CommonBase { ); bytes memory calls = getMintEncoded(config, liquidity, recipient, hookData); // add extra wei because modifyLiquidities may be rounding up, LiquidityAmounts is imprecise? - bytes[] memory result = lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); - - return abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); + delta = hook.deltas(0); } function increaseLiquidity( @@ -56,10 +58,10 @@ abstract contract LiquidityOperations is CommonBase { PositionConfig memory config, uint256 liquidityToAdd, bytes memory hookData - ) internal returns (BalanceDelta) { + ) internal returns (BalanceDelta delta) { bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, hookData); - bytes[] memory result = lpm.modifyLiquidities(calls, _deadline); - return abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities(calls, _deadline); + delta = hook.deltas(0); } // do not make external call before unlockAndExecute, allows us to test reverts @@ -68,29 +70,29 @@ abstract contract LiquidityOperations is CommonBase { PositionConfig memory config, uint256 liquidityToRemove, bytes memory hookData - ) internal returns (BalanceDelta) { + ) internal returns (BalanceDelta delta) { bytes memory calls = getDecreaseEncoded(tokenId, config, liquidityToRemove, hookData); - bytes[] memory result = lpm.modifyLiquidities(calls, _deadline); - return abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities(calls, _deadline); + delta = hook.deltas(0); } function collect(uint256 tokenId, PositionConfig memory config, bytes memory hookData) internal - returns (BalanceDelta) + returns (BalanceDelta delta) { bytes memory calls = getCollectEncoded(tokenId, config, hookData); - bytes[] memory result = lpm.modifyLiquidities(calls, _deadline); - return abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities(calls, _deadline); + delta = hook.deltas(0); } // This is encoded with close calls. Not all burns need to be encoded with closes if there is no liquidity in the position. function burn(uint256 tokenId, PositionConfig memory config, bytes memory hookData) internal - returns (BalanceDelta) + returns (BalanceDelta delta) { bytes memory calls = getBurnEncoded(tokenId, config, hookData); - bytes[] memory result = lpm.modifyLiquidities(calls, _deadline); - return abi.decode(result[0], (BalanceDelta)); + lpm.modifyLiquidities(calls, _deadline); + delta = hook.deltas(0); } // Helper functions for getting encoded calldata for .modifyLiquidities @@ -147,4 +149,8 @@ abstract contract LiquidityOperations is CommonBase { // Close needed on burn in case there is liquidity left in the position. return planner.finalize(config.poolKey); } + + function snapLastDelta() internal returns (BalanceDelta delta) { + delta = hook.deltas(hook.getDeltasLength() - 1); // just want the most recetly written to delta + } } diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index 7df86c3f..1dae0bf0 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol"; import {PositionManager} from "../../src/PositionManager.sol"; @@ -11,12 +12,20 @@ import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {LiquidityOperations} from "./LiquidityOperations.sol"; import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol"; import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; +import {HookSavesDelta} from "./HookSavesDelta.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 { uint256 constant STARTING_USER_BALANCE = 10_000_000 ether; IAllowanceTransfer permit2; + address hookAddr = address(uint160(Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); + + function deployPosmHookSavesDelta() public { + HookSavesDelta impl = new HookSavesDelta(); + vm.etch(hookAddr, address(impl).code); + hook = HookSavesDelta(hookAddr); + } function deployAndApprovePosm(IPoolManager poolManager) public { deployPosm(poolManager); From 0449cac584fcc93de7022ae19082e10544be8dbb Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 29 Jul 2024 17:51:05 -0400 Subject: [PATCH 07/23] remove return values --- .../PositionManager_burn_empty.snap | 2 +- .../PositionManager_burn_empty_native.snap | 2 +- .../PositionManager_burn_nonEmpty.snap | 2 +- .../PositionManager_burn_nonEmpty_native.snap | 2 +- .forge-snapshots/PositionManager_collect.snap | 2 +- .../PositionManager_collect_native.snap | 2 +- .../PositionManager_collect_sameRange.snap | 2 +- .../PositionManager_decreaseLiquidity.snap | 2 +- ...itionManager_decreaseLiquidity_native.snap | 2 +- .../PositionManager_decrease_burnEmpty.snap | 2 +- ...tionManager_decrease_burnEmpty_native.snap | 2 +- ...nager_decrease_sameRange_allLiquidity.snap | 2 +- ...sitionManager_increaseLiquidity_erc20.snap | 2 +- ...itionManager_increaseLiquidity_native.snap | 2 +- ...crease_autocompoundExactUnclaimedFees.snap | 2 +- ...increase_autocompoundExcessFeesCredit.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...anager_mint_warmedPool_differentRange.snap | 2 +- ...tionManager_multicall_initialize_mint.snap | 2 +- src/PositionManager.sol | 57 +++++++------------ src/base/BaseActionsRouter.sol | 1 - src/base/BaseActionsRouterReturns.sol | 55 ------------------ src/interfaces/IPositionManager.sol | 3 +- test/position-managers/NativeToken.t.sol | 2 +- test/position-managers/PositionManager.t.sol | 4 +- test/shared/LiquidityOperations.sol | 2 +- 31 files changed, 49 insertions(+), 123 deletions(-) delete mode 100644 src/base/BaseActionsRouterReturns.sol diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index 1b58562d..6d0dd6f1 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -49196 \ No newline at end of file +47282 \ 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 e355943e..b25f0e53 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -49014 \ No newline at end of file +47100 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty.snap b/.forge-snapshots/PositionManager_burn_nonEmpty.snap index 67498f64..0a95bcaf 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty.snap @@ -1 +1 @@ -159808 \ No newline at end of file +155776 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap index 507f2d5c..2f15346f 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap @@ -1 +1 @@ -152729 \ No newline at end of file +148698 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect.snap b/.forge-snapshots/PositionManager_collect.snap index 633f7fdc..57604f0f 100644 --- a/.forge-snapshots/PositionManager_collect.snap +++ b/.forge-snapshots/PositionManager_collect.snap @@ -1 +1 @@ -188308 \ No newline at end of file +183274 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index 3ec22d6a..c5165252 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -179460 \ No newline at end of file +174426 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index 633f7fdc..57604f0f 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -188308 \ No newline at end of file +183274 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity.snap b/.forge-snapshots/PositionManager_decreaseLiquidity.snap index d522203c..97eb6766 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity.snap @@ -1 +1 @@ -153851 \ No newline at end of file +148817 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index 17f43208..d70cfe45 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -145003 \ No newline at end of file +139969 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index 4ee229e8..a96f4b7a 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -165913 \ No newline at end of file +160830 \ 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 5f4e2340..1434cfdf 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -158652 \ No newline at end of file +153569 \ 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 37a2aae5..eeb85fed 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -166567 \ No newline at end of file +161533 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index e7e9dc6e..6b843271 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -189790 \ No newline at end of file +184756 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index 01886ef2..d371a66c 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -171673 \ No newline at end of file +166639 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index bf0cfe74..6b777d6a 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -152596 \ No newline at end of file +147562 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index 94c0a7b3..dc1c06c5 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -208652 \ No newline at end of file +203618 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index 21fe5a19..b9f41110 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -426969 \ No newline at end of file +421915 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 0aa4da2d..17dc54e5 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -391752 \ No newline at end of file +386698 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index 387c5aee..3a8821e1 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -398690 \ No newline at end of file +393636 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index be487fc8..f2cc6caa 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -352551 \ No newline at end of file +347497 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index e5e6cc84..e8c2fa16 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -353193 \ No newline at end of file +348139 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index 22a69dac..45a6b863 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -278775 \ No newline at end of file +273721 \ 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 c2a73544..6a2d73e5 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -358569 \ No newline at end of file +353515 \ 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 4b0d6a3c..455ee9d8 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -422319 \ No newline at end of file +417133 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 4b50c97e..3b81ea7a 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -21,7 +21,7 @@ import {Multicall} from "./base/Multicall.sol"; import {PoolInitializer} from "./base/PoolInitializer.sol"; import {DeltaResolver} from "./base/DeltaResolver.sol"; import {PositionConfig, PositionConfigLibrary} from "./libraries/PositionConfig.sol"; -import {BaseActionsRouterReturns} from "./base/BaseActionsRouterReturns.sol"; +import {BaseActionsRouter} from "./base/BaseActionsRouter.sol"; import {Actions} from "./libraries/Actions.sol"; contract PositionManager is @@ -32,7 +32,7 @@ contract PositionManager is SafeCallback, DeltaResolver, ReentrancyLock, - BaseActionsRouterReturns + BaseActionsRouter { using SafeTransferLib for *; using CurrencyLibrary for Currency; @@ -51,7 +51,7 @@ contract PositionManager is IAllowanceTransfer public immutable permit2; constructor(IPoolManager _poolManager, IAllowanceTransfer _permit2) - BaseActionsRouterReturns(_poolManager) + BaseActionsRouter(_poolManager) ERC721Permit("Uniswap V4 Positions NFT", "UNI-V4-POSM", "1") { permit2 = _permit2; @@ -63,29 +63,26 @@ contract PositionManager is } /// @param unlockData is an encoding of actions, params, and currencies - /// @return returnData is the endocing of each actions return information function modifyLiquidities(bytes calldata unlockData, uint256 deadline) external payable isNotLocked checkDeadline(deadline) - returns (bytes[] memory) { - // For now POSM will bubble up sub call return values. - return _executeActions(unlockData); + _executeActions(unlockData); } - function _handleAction(uint256 action, bytes calldata params) internal override returns (bytes memory) { + function _handleAction(uint256 action, bytes calldata params) internal override { if (action == Actions.INCREASE_LIQUIDITY) { - return _increase(params); + _increase(params); } else if (action == Actions.DECREASE_LIQUIDITY) { - return _decrease(params); + _decrease(params); } else if (action == Actions.MINT_POSITION) { - return _mint(params); + _mint(params); } else if (action == Actions.CLOSE_CURRENCY) { - return _close(params); + _close(params); } else if (action == Actions.BURN_POSITION) { - return _burn(params); + _burn(params); } else { revert UnsupportedAction(action); } @@ -96,22 +93,19 @@ contract PositionManager is } /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes hookData - /// @return returns an encoding of the BalanceDelta applied by this increase call, including credited fees. /// @dev Calling increase with 0 liquidity will credit the caller with any underlying fees of the position - function _increase(bytes memory params) internal returns (bytes memory) { + function _increase(bytes memory params) internal { (uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes memory hookData) = abi.decode(params, (uint256, PositionConfig, uint256, bytes)); if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); // Note: The tokenId is used as the salt for this position, so every minted position has unique storage in the pool manager. - BalanceDelta delta = _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); - return abi.encode(delta); + _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); } /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes hookData - /// @return returns an encoding of the BalanceDelta applied by this increase call, including credited fees. /// @dev Calling decrease with 0 liquidity will credit the caller with any underlying fees of the position - function _decrease(bytes memory params) internal returns (bytes memory) { + function _decrease(bytes memory params) internal { (uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes memory hookData) = abi.decode(params, (uint256, PositionConfig, uint256, bytes)); @@ -119,13 +113,11 @@ contract PositionManager is if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); // Note: the tokenId is used as the salt. - BalanceDelta delta = _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); - return abi.encode(delta); + _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); } /// @param params is an encoding of PositionConfig memory config, uint256 liquidity, address recipient, bytes hookData where recipient is the receiver / owner of the ERC721 - /// @return returns an encoding of the BalanceDelta from the initial increase - function _mint(bytes memory params) internal returns (bytes memory) { + function _mint(bytes memory params) internal { (PositionConfig memory config, uint256 liquidity, address owner, bytes memory hookData) = abi.decode(params, (PositionConfig, uint256, address, bytes)); @@ -138,16 +130,13 @@ contract PositionManager is _mint(owner, tokenId); // _beforeModify is not called here because the tokenId is newly minted - BalanceDelta delta = _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); + _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); positionConfigs[tokenId] = config.toId(); - - return abi.encode(delta); } /// @param params is an encoding of the Currency to close - /// @return bytes an encoding of int256 the balance of the currency being settled by this call - function _close(bytes memory params) internal returns (bytes memory) { + function _close(bytes memory params) internal { (Currency currency) = abi.decode(params, (Currency)); // this address has applied all deltas on behalf of the user/owner // it is safe to close this entire delta because of slippage checks throughout the batched calls. @@ -163,13 +152,11 @@ contract PositionManager is } else if (currencyDelta > 0) { _take(currency, caller, uint256(currencyDelta)); } - - return abi.encode(currencyDelta); } /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, bytes hookData /// @dev this is overloaded with ERC721Permit._burn - function _burn(bytes memory params) internal returns (bytes memory) { + function _burn(bytes memory params) internal { (uint256 tokenId, PositionConfig memory config, bytes memory hookData) = abi.decode(params, (uint256, PositionConfig, bytes)); @@ -178,21 +165,17 @@ contract PositionManager is uint256 liquidity = uint256(_getPositionLiquidity(config, tokenId)); // Can only call modify if there is non zero liquidity. - BalanceDelta delta; - - if (liquidity > 0) delta = _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); + if (liquidity > 0) _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); delete positionConfigs[tokenId]; // Burn the token. _burn(tokenId); - return abi.encode(delta); } function _modifyLiquidity(PositionConfig memory config, int256 liquidityChange, bytes32 salt, bytes memory hookData) internal - returns (BalanceDelta liquidityDelta) { - (liquidityDelta,) = poolManager.modifyLiquidity( + poolManager.modifyLiquidity( config.poolKey, IPoolManager.ModifyLiquidityParams({ tickLower: config.tickLower, diff --git a/src/base/BaseActionsRouter.sol b/src/base/BaseActionsRouter.sol index 1cb1b50a..8a03bd27 100644 --- a/src/base/BaseActionsRouter.sol +++ b/src/base/BaseActionsRouter.sol @@ -38,7 +38,6 @@ abstract contract BaseActionsRouter is SafeCallback { _handleAction(action, params[actionIndex]); } - // TODO do we want to return anything? return ""; } diff --git a/src/base/BaseActionsRouterReturns.sol b/src/base/BaseActionsRouterReturns.sol deleted file mode 100644 index ed4c6270..00000000 --- a/src/base/BaseActionsRouterReturns.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.24; - -import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; -import {SafeCallback} from "./SafeCallback.sol"; -import {CalldataDecoder} from "../libraries/CalldataDecoder.sol"; - -/// @notice Abstract contract for performing a combination of actions on Uniswap v4. -/// @dev Suggested uint256 action values are defined in Actions.sol, however any definition can be used -/// @dev This contract handles return values from sub calls to _handleAction. -abstract contract BaseActionsRouterReturns is SafeCallback { - using CalldataDecoder for bytes; - - /// @notice emitted when different numbers of parameters and actions are provided - error LengthMismatch(); - - /// @notice emitted when an inheriting contract does not support an action - error UnsupportedAction(uint256 action); - - constructor(IPoolManager _poolManager) SafeCallback(_poolManager) {} - - /// @notice internal function that triggers the execution of a set of actions on v4 - /// @dev inheriting contracts should call this function to trigger execution - function _executeActions(bytes calldata unlockData) internal returns (bytes[] memory) { - return abi.decode(poolManager.unlock(unlockData), (bytes[])); - } - - /// @notice function that is called by the PoolManager through the SafeCallback.unlockCallback - function _unlockCallback(bytes calldata data) internal override returns (bytes memory) { - // abi.decode(data, (uint256[], bytes[])); - (uint256[] calldata actions, bytes[] calldata params) = data.decodeActionsRouterParams(); - - uint256 numActions = actions.length; - if (numActions != params.length) revert LengthMismatch(); - - bytes[] memory results = new bytes[](numActions); - for (uint256 actionIndex = 0; actionIndex < numActions; actionIndex++) { - uint256 action = actions[actionIndex]; - - results[actionIndex] = _handleAction(action, params[actionIndex]); - } - - return abi.encode(results); - } - - /// @notice function to handle the parsing and execution of an action and its parameters - function _handleAction(uint256 action, bytes calldata params) internal virtual returns (bytes memory); - - /// @notice function that returns address considered executer of the actions - /// @dev The other context functions, _msgData and _msgValue, are not supported by this contract - /// In many contracts this will be the address that calls the initial entry point that calls `_executeActions` - /// `msg.sender` shouldnt be used, as this will be the v4 pool manager contract that calls `unlockCallback` - /// If using ReentrancyLock.sol, this function can return Locker.get() - locker of the contract - function _msgSender() internal view virtual returns (address); -} diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index d5ff7883..ebf0b482 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -17,8 +17,7 @@ interface IPositionManager { /// @notice Batches many liquidity modification calls to pool manager /// @param payload is an encoding of actions, and parameters for those actions /// @param deadline is the deadline for the batched actions to be executed - /// @return returnData is the endocing of each actions return information - function modifyLiquidities(bytes calldata payload, uint256 deadline) external payable returns (bytes[] memory); + function modifyLiquidities(bytes calldata payload, uint256 deadline) external payable; function nextTokenId() external view returns (uint256); } diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index 54ff1b2b..4438afbc 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -260,7 +260,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { ); bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, ZERO_BYTES); // double the liquidity - bytes[] memory result = lpm.modifyLiquidities{value: amount0 + 1 wei}(calls, _deadline); // TODO: off by one wei + lpm.modifyLiquidities{value: amount0 + 1 wei}(calls, _deadline); // TODO: off by one wei BalanceDelta delta = snapLastDelta(); // verify position liquidity increased diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index 747525dc..d41e39fc 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -22,7 +22,7 @@ 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 {BaseActionsRouterReturns} from "../../src/base/BaseActionsRouterReturns.sol"; +import {BaseActionsRouter} from "../../src/base/BaseActionsRouter.sol"; import {LiquidityFuzzers} from "../shared/fuzz/LiquidityFuzzers.sol"; import {Planner, Plan} from "../shared/Planner.sol"; @@ -60,7 +60,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { bytes[] memory badParams = new bytes[](1); - vm.expectRevert(BaseActionsRouterReturns.LengthMismatch.selector); + vm.expectRevert(BaseActionsRouter.LengthMismatch.selector); lpm.modifyLiquidities(abi.encode(planner.actions, badParams), block.timestamp + 1); } diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index 9558726c..93ce85df 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -150,7 +150,7 @@ abstract contract LiquidityOperations is CommonBase { return planner.finalize(config.poolKey); } - function snapLastDelta() internal returns (BalanceDelta delta) { + function snapLastDelta() internal view returns (BalanceDelta delta) { delta = hook.deltas(hook.getDeltasLength() - 1); // just want the most recetly written to delta } } From 47bbc6d8b967e3cb729bcaee0764380d20fd6381 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 29 Jul 2024 17:53:27 -0400 Subject: [PATCH 08/23] add burn comment --- src/PositionManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 3b81ea7a..76adcd29 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -82,6 +82,7 @@ contract PositionManager is } else if (action == Actions.CLOSE_CURRENCY) { _close(params); } else if (action == Actions.BURN_POSITION) { + // Will automatically decrease liquidity to 0 if the position is not already empty. _burn(params); } else { revert UnsupportedAction(action); From 7c911cb007a19a9bd23a8c7c81be5b0e11f18fd3 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 29 Jul 2024 18:33:35 -0400 Subject: [PATCH 09/23] make gas snapshots more accurate, remove hook --- .../PositionManager_burn_empty.snap | 2 +- .../PositionManager_burn_empty_native.snap | 2 +- .../PositionManager_burn_nonEmpty.snap | 2 +- .../PositionManager_burn_nonEmpty_native.snap | 2 +- .forge-snapshots/PositionManager_collect.snap | 2 +- .../PositionManager_collect_native.snap | 2 +- .../PositionManager_collect_sameRange.snap | 2 +- .../PositionManager_decreaseLiquidity.snap | 2 +- ...itionManager_decreaseLiquidity_native.snap | 2 +- .../PositionManager_decrease_burnEmpty.snap | 2 +- ...tionManager_decrease_burnEmpty_native.snap | 2 +- ...nager_decrease_sameRange_allLiquidity.snap | 2 +- ...sitionManager_increaseLiquidity_erc20.snap | 2 +- ...itionManager_increaseLiquidity_native.snap | 2 +- ...crease_autocompoundExactUnclaimedFees.snap | 2 +- ...increase_autocompoundExcessFeesCredit.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...anager_mint_warmedPool_differentRange.snap | 2 +- test/position-managers/Execute.t.sol | 5 +--- test/position-managers/FeeCollection.t.sol | 3 ++- test/position-managers/Gas.t.sol | 5 +--- test/position-managers/PositionManager.t.sol | 9 ++++--- test/shared/LiquidityOperations.sol | 27 +++++-------------- 28 files changed, 39 insertions(+), 56 deletions(-) diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index 6d0dd6f1..3bc96e31 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -47282 \ No newline at end of file +47272 \ 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 b25f0e53..d7623a2c 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -47100 \ No newline at end of file +47090 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty.snap b/.forge-snapshots/PositionManager_burn_nonEmpty.snap index 0a95bcaf..49379c42 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty.snap @@ -1 +1 @@ -155776 \ No newline at end of file +130136 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap index 2f15346f..9803c797 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap @@ -1 +1 @@ -148698 \ No newline at end of file +123057 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect.snap b/.forge-snapshots/PositionManager_collect.snap index 57604f0f..0c61cc2c 100644 --- a/.forge-snapshots/PositionManager_collect.snap +++ b/.forge-snapshots/PositionManager_collect.snap @@ -1 +1 @@ -183274 \ No newline at end of file +151223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index c5165252..3767f77c 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -174426 \ No newline at end of file +142375 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index 57604f0f..0c61cc2c 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -183274 \ No newline at end of file +151223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity.snap b/.forge-snapshots/PositionManager_decreaseLiquidity.snap index 97eb6766..f7274df9 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity.snap @@ -1 +1 @@ -148817 \ No newline at end of file +116766 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index d70cfe45..8ef6aa1f 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -139969 \ No newline at end of file +109375 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index a96f4b7a..3dfa8ec0 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -160830 \ No newline at end of file +135180 \ 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 1434cfdf..86a341b3 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -153569 \ No newline at end of file +127919 \ 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 eeb85fed..28c9ff85 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -161533 \ No newline at end of file +129482 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index 6b843271..227e6bc8 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -184756 \ No newline at end of file +152738 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index d371a66c..dc7f9de9 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -166639 \ No newline at end of file +134621 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index 6b777d6a..e7eb74f8 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -147562 \ No newline at end of file +135444 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index dc1c06c5..a4388ec1 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -203618 \ No newline at end of file +171600 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index b9f41110..13b5f4bd 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -421915 \ No newline at end of file +372797 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 17dc54e5..1aa22312 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -386698 \ No newline at end of file +337580 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index 3a8821e1..e431c81e 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -393636 \ No newline at end of file +344518 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index f2cc6caa..e7e973c7 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -347497 \ No newline at end of file +315479 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index e8c2fa16..139fcc42 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -348139 \ No newline at end of file +316121 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index 45a6b863..a79acafa 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -273721 \ No newline at end of file +241703 \ 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 6a2d73e5..febc1a43 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -353515 \ No newline at end of file +321497 \ No newline at end of file diff --git a/test/position-managers/Execute.t.sol b/test/position-managers/Execute.t.sol index 7b38d73d..54d4f343 100644 --- a/test/position-managers/Execute.t.sol +++ b/test/position-managers/Execute.t.sol @@ -41,10 +41,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - // deploy this since all functions used in LiquidityOperations require the snapshotting to work - deployPosmHookSavesDelta(); - - (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); // Requires currency0 and currency1 to be set in base Deployers contract. deployAndApprovePosm(manager); diff --git a/test/position-managers/FeeCollection.t.sol b/test/position-managers/FeeCollection.t.sol index 472cd91d..8f59f89e 100644 --- a/test/position-managers/FeeCollection.t.sol +++ b/test/position-managers/FeeCollection.t.sol @@ -159,8 +159,9 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenIdAlice = lpm.nextTokenId(); vm.startPrank(alice); - BalanceDelta lpDeltaAlice = mint(config, liquidityAlice, alice, ZERO_BYTES); + mint(config, liquidityAlice, alice, ZERO_BYTES); vm.stopPrank(); + BalanceDelta lpDeltaAlice = snapLastDelta(); uint256 tokenIdBob = lpm.nextTokenId(); vm.startPrank(bob); diff --git a/test/position-managers/Gas.t.sol b/test/position-managers/Gas.t.sol index 870703e1..2af43e93 100644 --- a/test/position-managers/Gas.t.sol +++ b/test/position-managers/Gas.t.sol @@ -49,10 +49,7 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { deployFreshManagerAndRouters(); deployMintAndApprove2Currencies(); - // This is needed to receive return deltas from modifyLiquidity calls. - deployPosmHookSavesDelta(); - - (key, poolId) = initPool(currency0, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); + (key, poolId) = initPool(currency0, currency1, IHooks(address(0)), 3000, SQRT_PRICE_1_1, ZERO_BYTES); (nativeKey,) = initPool(CurrencyLibrary.NATIVE, currency1, IHooks(hook), 3000, SQRT_PRICE_1_1, ZERO_BYTES); FEE_WAD = uint256(key.fee).mulDivDown(FixedPointMathLib.WAD, 1_000_000); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index d41e39fc..563987bc 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -100,7 +100,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); uint256 tokenId = lpm.nextTokenId(); - BalanceDelta delta = mint(config, liquidityToAdd, address(this), ZERO_BYTES); + mint(config, liquidityToAdd, address(this), ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); assertEq(tokenId, 1); assertEq(lpm.nextTokenId(), 2); @@ -134,7 +135,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); uint256 tokenId = lpm.nextTokenId(); - BalanceDelta delta = mint(config, liquidityToAdd, address(this), ZERO_BYTES); + mint(config, liquidityToAdd, address(this), ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); uint256 balance0After = currency0.balanceOfSelf(); uint256 balance1After = currency1.balanceOfSelf(); @@ -161,7 +163,8 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); uint256 balance0BeforeAlice = currency0.balanceOf(alice); uint256 balance1BeforeAlice = currency1.balanceOf(alice); - BalanceDelta delta = mint(config, liquidityToAdd, alice, ZERO_BYTES); + mint(config, liquidityToAdd, alice, ZERO_BYTES); + BalanceDelta delta = snapLastDelta(); assertEq(tokenId, 1); assertEq(lpm.ownerOf(tokenId), alice); diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index 93ce85df..bf0f012b 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -24,13 +24,9 @@ abstract contract LiquidityOperations is CommonBase { uint256 _deadline = block.timestamp + 1; - function mint(PositionConfig memory config, uint256 liquidity, address recipient, bytes memory hookData) - internal - returns (BalanceDelta delta) - { + function mint(PositionConfig memory config, uint256 liquidity, address recipient, bytes memory hookData) internal { bytes memory calls = getMintEncoded(config, liquidity, recipient, hookData); lpm.modifyLiquidities(calls, _deadline); - delta = hook.deltas(0); } function mintWithNative( @@ -39,7 +35,7 @@ abstract contract LiquidityOperations is CommonBase { uint256 liquidity, address recipient, bytes memory hookData - ) internal returns (BalanceDelta delta) { + ) internal { // determine the amount of ETH to send on-mint (uint256 amount0,) = LiquidityAmounts.getAmountsForLiquidity( sqrtPriceX96, @@ -50,7 +46,6 @@ abstract contract LiquidityOperations is CommonBase { bytes memory calls = getMintEncoded(config, liquidity, recipient, hookData); // add extra wei because modifyLiquidities may be rounding up, LiquidityAmounts is imprecise? lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); - delta = hook.deltas(0); } function increaseLiquidity( @@ -58,10 +53,9 @@ abstract contract LiquidityOperations is CommonBase { PositionConfig memory config, uint256 liquidityToAdd, bytes memory hookData - ) internal returns (BalanceDelta delta) { + ) internal { bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, hookData); lpm.modifyLiquidities(calls, _deadline); - delta = hook.deltas(0); } // do not make external call before unlockAndExecute, allows us to test reverts @@ -70,29 +64,20 @@ abstract contract LiquidityOperations is CommonBase { PositionConfig memory config, uint256 liquidityToRemove, bytes memory hookData - ) internal returns (BalanceDelta delta) { + ) internal { bytes memory calls = getDecreaseEncoded(tokenId, config, liquidityToRemove, hookData); lpm.modifyLiquidities(calls, _deadline); - delta = hook.deltas(0); } - function collect(uint256 tokenId, PositionConfig memory config, bytes memory hookData) - internal - returns (BalanceDelta delta) - { + function collect(uint256 tokenId, PositionConfig memory config, bytes memory hookData) internal { bytes memory calls = getCollectEncoded(tokenId, config, hookData); lpm.modifyLiquidities(calls, _deadline); - delta = hook.deltas(0); } // This is encoded with close calls. Not all burns need to be encoded with closes if there is no liquidity in the position. - function burn(uint256 tokenId, PositionConfig memory config, bytes memory hookData) - internal - returns (BalanceDelta delta) - { + function burn(uint256 tokenId, PositionConfig memory config, bytes memory hookData) internal { bytes memory calls = getBurnEncoded(tokenId, config, hookData); lpm.modifyLiquidities(calls, _deadline); - delta = hook.deltas(0); } // Helper functions for getting encoded calldata for .modifyLiquidities From 03cf4537ace8d82230f8eea8c3d4818c1d1ade24 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 29 Jul 2024 18:39:08 -0400 Subject: [PATCH 10/23] move to 1 planner, fix merge conf --- test/router/V4Router.gas.t.sol | 6 ++-- test/router/V4Router.t.sol | 6 ++-- test/shared/ActionsRouterPlanner.sol | 51 ---------------------------- test/shared/RoutingTestHelpers.sol | 4 +-- 4 files changed, 8 insertions(+), 59 deletions(-) delete mode 100644 test/shared/ActionsRouterPlanner.sol diff --git a/test/router/V4Router.gas.t.sol b/test/router/V4Router.gas.t.sol index bfbd76fd..4f7c99b5 100644 --- a/test/router/V4Router.gas.t.sol +++ b/test/router/V4Router.gas.t.sol @@ -6,16 +6,16 @@ import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol import {IV4Router} from "../../src/interfaces/IV4Router.sol"; import {RoutingTestHelpers} from "../shared/RoutingTestHelpers.sol"; -import {Plan, ActionsRouterPlanner} from "../shared/ActionsRouterPlanner.sol"; +import {Plan, Planner} from "../shared/Planner.sol"; import {Actions} from "../../src/libraries/Actions.sol"; contract V4RouterTest is RoutingTestHelpers, GasSnapshot { using CurrencyLibrary for Currency; - using ActionsRouterPlanner for Plan; + using Planner for Plan; function setUp() public { setupRouterCurrenciesAndPoolsWithLiquidity(); - plan = ActionsRouterPlanner.init(); + plan = Planner.init(); } function test_gas_bytecodeSize() public { diff --git a/test/router/V4Router.t.sol b/test/router/V4Router.t.sol index 194da80b..40d825f5 100644 --- a/test/router/V4Router.t.sol +++ b/test/router/V4Router.t.sol @@ -4,16 +4,16 @@ pragma solidity ^0.8.19; import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; import {IV4Router} from "../../src/interfaces/IV4Router.sol"; import {RoutingTestHelpers} from "../shared/RoutingTestHelpers.sol"; -import {Plan, ActionsRouterPlanner} from "../shared/ActionsRouterPlanner.sol"; +import {Plan, Planner} from "../shared/Planner.sol"; import {Actions} from "../../src/libraries/Actions.sol"; contract V4RouterTest is RoutingTestHelpers { using CurrencyLibrary for Currency; - using ActionsRouterPlanner for Plan; + using Planner for Plan; function setUp() public { setupRouterCurrenciesAndPoolsWithLiquidity(); - plan = ActionsRouterPlanner.init(); + plan = Planner.init(); } function test_swapExactInputSingle_zeroForOne() public { diff --git a/test/shared/ActionsRouterPlanner.sol b/test/shared/ActionsRouterPlanner.sol deleted file mode 100644 index 09803eeb..00000000 --- a/test/shared/ActionsRouterPlanner.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.24; - -import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; -import {Actions} from "../../src/libraries/Actions.sol"; - -struct Plan { - uint256[] actions; - bytes[] params; -} - -library ActionsRouterPlanner { - using ActionsRouterPlanner for Plan; - - function init() internal pure returns (Plan memory plan) { - return Plan({actions: new uint256[](0), params: new bytes[](0)}); - } - - function add(Plan memory plan, uint256 action, bytes memory param) internal pure returns (Plan memory) { - uint256[] memory actions = new uint256[](plan.actions.length + 1); - bytes[] memory params = new bytes[](plan.params.length + 1); - - for (uint256 i; i < actions.length - 1; i++) { - // Copy from plan. - actions[i] = plan.actions[i]; - params[i] = plan.params[i]; - } - - actions[actions.length - 1] = action; - params[params.length - 1] = param; - - plan.actions = actions; - plan.params = params; - - return plan; - } - - function encode(Plan memory plan) internal pure returns (bytes memory) { - return abi.encode(plan.actions, plan.params); - } - - function finalizeSwap(Plan memory plan, Currency inputCurrency, Currency outputCurrency, address recipient) - internal - pure - returns (bytes memory) - { - plan = plan.add(Actions.SETTLE_ALL, abi.encode(inputCurrency)); - plan = plan.add(Actions.TAKE_ALL, abi.encode(outputCurrency, recipient)); - return plan.encode(); - } -} diff --git a/test/shared/RoutingTestHelpers.sol b/test/shared/RoutingTestHelpers.sol index b1af43cf..b222e631 100644 --- a/test/shared/RoutingTestHelpers.sol +++ b/test/shared/RoutingTestHelpers.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; import {PoolModifyLiquidityTest} from "@uniswap/v4-core/src/test/PoolModifyLiquidityTest.sol"; import {V4RouterImplementation} from "../shared/implementation/V4RouterImplementation.sol"; -import {Plan, ActionsRouterPlanner} from "../shared/ActionsRouterPlanner.sol"; +import {Plan, Planner} from "../shared/Planner.sol"; import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol"; import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {PathKey} from "../../src/libraries/PathKey.sol"; @@ -21,7 +21,7 @@ import {IV4Router} from "../../src/interfaces/IV4Router.sol"; /// @notice A shared test contract that wraps the v4-core deployers contract and exposes basic helpers for swapping with the router. contract RoutingTestHelpers is Test, Deployers { - using ActionsRouterPlanner for Plan; + using Planner for Plan; PoolModifyLiquidityTest positionManager; V4RouterImplementation router; From 2aba16d2af26862c694bf4d23d89603d574161b1 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Mon, 29 Jul 2024 21:21:51 -0400 Subject: [PATCH 11/23] sweep currency, pr comments --- ...sitionManager_increaseLiquidity_erc20.snap | 2 +- ...itionManager_increaseLiquidity_native.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...anager_mint_warmedPool_differentRange.snap | 2 +- ...tionManager_multicall_initialize_mint.snap | 2 +- src/PositionManager.sol | 22 +++++-------------- src/interfaces/IPositionManager.sol | 1 - src/libraries/Actions.sol | 2 +- test/position-managers/Gas.t.sol | 8 ++++++- .../position-managers/IncreaseLiquidity.t.sol | 6 ++--- test/position-managers/NativeToken.t.sol | 19 ++++++++++++++-- 16 files changed, 44 insertions(+), 34 deletions(-) diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index 5afd30aa..2761a124 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -148697 \ No newline at end of file +148651 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index 47315a1b..2690fb41 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -133879 \ No newline at end of file +133778 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index aa48f77b..142f96f1 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -368776 \ No newline at end of file +368730 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 70db2026..cfb6dbc3 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -336858 \ No newline at end of file +336757 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index 470829f3..08f217a2 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -343796 \ No newline at end of file +346786 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index e633870e..24486466 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -311458 \ No newline at end of file +311412 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index 0c7a3cc5..7c4ba42a 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -312100 \ No newline at end of file +312054 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index 5665f1b7..5dc58a62 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -237682 \ No newline at end of file +237636 \ 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 a9ceafa3..8c940efc 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -317476 \ No newline at end of file +317430 \ 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 8a1a7a16..12ef466c 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -413266 \ No newline at end of file +413220 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index f419973c..891696e3 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -85,8 +85,8 @@ contract PositionManager is return _burn(params); } else if (action == Actions.SETTLE_WITH_BALANCE) { return _settleWithBalance(params); - } else if (action == Actions.SWEEP_ERC20_TO) { - _sweepERC20To(params); + } else if (action == Actions.SWEEP) { + _sweep(params); } else { revert UnsupportedAction(action); } @@ -158,9 +158,6 @@ contract PositionManager is address caller = _msgSender(); if (currencyDelta < 0) { _settle(currency, caller, uint256(-currencyDelta)); - - // if there are native tokens left over after settling, return to locker - if (currency.isNative()) _sweepNativeToken(caller); } else if (currencyDelta > 0) { _take(currency, caller, uint256(currencyDelta)); } @@ -171,7 +168,6 @@ contract PositionManager is /// @param params is an encoding of Currency, uint256 amount /// @dev if amount == FULL_DELTA, it settles the full negative delta /// @dev uses this addresses balance to settle a negative delta - /// @dev Should not be called for NATIVE settling bc does not sweep. function _settleWithBalance(bytes memory params) internal returns (bytes memory) { (Currency currency, uint256 amount) = abi.decode(params, (Currency, uint256)); @@ -230,18 +226,12 @@ contract PositionManager is liquidity = poolManager.getPositionLiquidity(config.poolKey.toId(), positionId); } - /// @dev Send excess native tokens back to the recipient (locker) - /// @param recipient the receiver of the excess native tokens. Should be the caller, the one that sent the native tokens - function _sweepNativeToken(address recipient) internal { - uint256 nativeBalance = address(this).balance; - if (nativeBalance > 0) recipient.safeTransferETH(nativeBalance); - } - + /// @notice Sweeps the entire contract balance of specified currency to the recipient /// @param params an encoding of Currency, address - function _sweepERC20To(bytes calldata params) internal { + function _sweep(bytes calldata params) internal { (Currency currency, address to) = abi.decode(params, (Currency, address)); - uint256 tokenBalance = ERC20(Currency.unwrap(currency)).balanceOf(address(this)); - if (tokenBalance > 0) currency.transfer(to, tokenBalance); + uint256 balance = currency.balanceOfSelf(); + if (balance > 0) currency.transfer(to, balance); } // implementation of abstract function DeltaResolver._pay diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index 958eb8fb..13287919 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -6,7 +6,6 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; interface IPositionManager { error NotApproved(address caller); error DeadlinePassed(); - error NothingToSettle(); error IncorrectUseOfTake(); error IncorrectUseOfSettle(); error IncorrectPositionConfigForTokenId(uint256 tokenId); diff --git a/src/libraries/Actions.sol b/src/libraries/Actions.sol index cf59d340..cc9bd683 100644 --- a/src/libraries/Actions.sol +++ b/src/libraries/Actions.sol @@ -27,5 +27,5 @@ library Actions { // settle using the balance contract uint256 constant SETTLE_WITH_BALANCE = 0x24; - uint256 constant SWEEP_ERC20_TO = 0x25; + uint256 constant SWEEP = 0x25; } diff --git a/test/position-managers/Gas.t.sol b/test/position-managers/Gas.t.sol index ef753869..ac4ebd12 100644 --- a/test/position-managers/Gas.t.sol +++ b/test/position-managers/Gas.t.sol @@ -376,7 +376,13 @@ contract GasTest is Test, PosmTestSetup, GasSnapshot { function test_gas_mint_native_excess() public { uint256 liquidityToAdd = 10_000 ether; - bytes memory calls = getMintEncoded(configNative, liquidityToAdd, address(this), ZERO_BYTES); + + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(configNative, liquidityToAdd, address(this), ZERO_BYTES)); + planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency0)); + planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency1)); + planner.add(Actions.SWEEP, abi.encode(CurrencyLibrary.NATIVE, address(this))); + bytes memory calls = planner.encode(); (uint256 amount0,) = LiquidityAmounts.getAmountsForLiquidity( SQRT_PRICE_1_1, diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 5cce961c..ca246376 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -343,8 +343,8 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); - planner.add(Actions.SWEEP_ERC20_TO, abi.encode(currency0, address(this))); - planner.add(Actions.SWEEP_ERC20_TO, abi.encode(currency1, address(this))); + planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); + planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); uint256 balanceBefore0 = currency0.balanceOf(address(this)); uint256 balanceBefore1 = currency1.balanceOf(address(this)); @@ -370,6 +370,6 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 0); assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amount0); - assertEq(currency1.balanceOf(address(this)), balanceBefore0 - amount0); + assertEq(currency1.balanceOf(address(this)), balanceBefore1 - amount1); } } diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index 90e22f56..b775e955 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -105,7 +105,15 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); uint256 tokenId = lpm.nextTokenId(); - bytes memory calls = getMintEncoded(config, liquidityToAdd, address(this), ZERO_BYTES); + + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityToAdd, address(this), ZERO_BYTES)); + planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency0)); + planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency1)); + // sweep the excess eth + planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); + + bytes memory calls = planner.encode(); (uint256 amount0,) = LiquidityAmounts.getAmountsForLiquidity( SQRT_PRICE_1_1, @@ -293,7 +301,14 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint128(liquidityToAdd) ); - bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, ZERO_BYTES); // double the liquidity + Plan memory planner = Planner.init(); + planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); + planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency0)); + planner.add(Actions.CLOSE_CURRENCY, abi.encode(nativeKey.currency1)); + // sweep the excess eth + planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); + bytes memory calls = planner.encode(); + bytes[] memory result = lpm.modifyLiquidities{value: amount0 * 2}(calls, _deadline); // overpay on increase liquidity BalanceDelta delta = abi.decode(result[0], (BalanceDelta)); From b3aa8741d64779a27f473e0795d8e9227b5cbfc2 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 10:21:47 -0400 Subject: [PATCH 12/23] rename, add liquidityDelta return param --- .forge-snapshots/PositionManager_burn_empty.snap | 2 +- .../PositionManager_burn_empty_native.snap | 2 +- .../PositionManager_burn_nonEmpty.snap | 2 +- .../PositionManager_burn_nonEmpty_native.snap | 2 +- .forge-snapshots/PositionManager_collect.snap | 2 +- .../PositionManager_collect_native.snap | 2 +- .../PositionManager_collect_sameRange.snap | 2 +- .../PositionManager_decreaseLiquidity.snap | 2 +- ...PositionManager_decreaseLiquidity_native.snap | 2 +- .../PositionManager_decrease_burnEmpty.snap | 2 +- ...ositionManager_decrease_burnEmpty_native.snap | 2 +- ...nManager_decrease_sameRange_allLiquidity.snap | 2 +- .../PositionManager_increaseLiquidity_erc20.snap | 2 +- ...PositionManager_increaseLiquidity_native.snap | 2 +- ..._increase_autocompoundExactUnclaimedFees.snap | 2 +- ...er_increase_autocompoundExcessFeesCredit.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .../PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .../PositionManager_mint_sameRange.snap | 2 +- ...onManager_mint_warmedPool_differentRange.snap | 2 +- ...ositionManager_multicall_initialize_mint.snap | 2 +- src/PositionManager.sol | 14 +++++++++----- test/position-managers/FeeCollection.t.sol | 10 +++++----- test/position-managers/NativeToken.t.sol | 16 ++++++++-------- test/position-managers/PositionManager.t.sol | 12 ++++++------ test/shared/LiquidityOperations.sol | 6 ------ test/shared/PosmTestSetup.sol | 6 ++++++ 30 files changed, 58 insertions(+), 54 deletions(-) diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index 956aeedb..2758ccf3 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -47268 \ No newline at end of file +47271 \ 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 54dddc50..462cc207 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -47085 \ No newline at end of file +47088 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty.snap b/.forge-snapshots/PositionManager_burn_nonEmpty.snap index 6724571f..d1f6268f 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty.snap @@ -1 +1 @@ -130121 \ No newline at end of file +130139 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap index 05e82712..cd0f3868 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap @@ -1 +1 @@ -123043 \ No newline at end of file +123060 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect.snap b/.forge-snapshots/PositionManager_collect.snap index 4ae1a565..0c61cc2c 100644 --- a/.forge-snapshots/PositionManager_collect.snap +++ b/.forge-snapshots/PositionManager_collect.snap @@ -1 +1 @@ -151205 \ No newline at end of file +151223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index 75a7dea8..3767f77c 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -142357 \ No newline at end of file +142375 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index 4ae1a565..0c61cc2c 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -151205 \ No newline at end of file +151223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity.snap b/.forge-snapshots/PositionManager_decreaseLiquidity.snap index 15369cb7..f7274df9 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity.snap @@ -1 +1 @@ -116748 \ No newline at end of file +116766 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index 146d7d1c..8ef6aa1f 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -109360 \ No newline at end of file +109375 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index de5debbb..31fc4741 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -135160 \ No newline at end of file +135178 \ 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 291860df..4be6bbf3 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -127900 \ No newline at end of file +127917 \ 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 71e7528d..28c9ff85 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -129464 \ No newline at end of file +129482 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index 1fa253ea..dfa8e719 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -152708 \ No newline at end of file +152726 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index 0017130e..c7b0f926 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -134591 \ No newline at end of file +134609 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index 44bd403f..32633ab4 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -135414 \ No newline at end of file +135432 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index 4c8b656d..c6e7ab8c 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -171570 \ No newline at end of file +171588 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index 8cf42c6f..43f34e63 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -372779 \ No newline at end of file +372827 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 4ab90f9a..412b757a 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -337562 \ No newline at end of file +337610 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index dd050f85..3ac91811 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -344500 \ No newline at end of file +344548 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index 344757fa..68be3acc 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -315461 \ No newline at end of file +315509 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index 8283ce88..ead48271 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -316103 \ No newline at end of file +316151 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index d1fac6b3..ee368a59 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -241685 \ No newline at end of file +241733 \ 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 51aff794..54413555 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -321479 \ No newline at end of file +321527 \ 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 384cfd87..ebe66360 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -417115 \ No newline at end of file +417163 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 76adcd29..537851ab 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -101,7 +101,7 @@ contract PositionManager is if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); // Note: The tokenId is used as the salt for this position, so every minted position has unique storage in the pool manager. - _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); + BalanceDelta liquidityDelta = _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); } /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, uint256 liquidity, bytes hookData @@ -114,7 +114,7 @@ contract PositionManager is if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); // Note: the tokenId is used as the salt. - _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); + BalanceDelta liquidityDelta = _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); } /// @param params is an encoding of PositionConfig memory config, uint256 liquidity, address recipient, bytes hookData where recipient is the receiver / owner of the ERC721 @@ -131,7 +131,7 @@ contract PositionManager is _mint(owner, tokenId); // _beforeModify is not called here because the tokenId is newly minted - _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); + BalanceDelta liquidityDelta = _modifyLiquidity(config, liquidity.toInt256(), bytes32(tokenId), hookData); positionConfigs[tokenId] = config.toId(); } @@ -165,8 +165,11 @@ contract PositionManager is if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId); uint256 liquidity = uint256(_getPositionLiquidity(config, tokenId)); + BalanceDelta liquidityDelta; // Can only call modify if there is non zero liquidity. - if (liquidity > 0) _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); + if (liquidity > 0) { + liquidityDelta = _modifyLiquidity(config, -(liquidity.toInt256()), bytes32(tokenId), hookData); + } delete positionConfigs[tokenId]; // Burn the token. @@ -175,8 +178,9 @@ contract PositionManager is function _modifyLiquidity(PositionConfig memory config, int256 liquidityChange, bytes32 salt, bytes memory hookData) internal + returns (BalanceDelta liquidityDelta) { - poolManager.modifyLiquidity( + (liquidityDelta,) = poolManager.modifyLiquidity( config.poolKey, IPoolManager.ModifyLiquidityParams({ tickLower: config.tickLower, diff --git a/test/position-managers/FeeCollection.t.sol b/test/position-managers/FeeCollection.t.sol index 8f59f89e..fa32bf44 100644 --- a/test/position-managers/FeeCollection.t.sol +++ b/test/position-managers/FeeCollection.t.sol @@ -75,7 +75,7 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1Before = currency1.balanceOfSelf(); collect(tokenId, config, ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); assertEq(uint256(int256(delta.amount1())), uint256(int256(expectedFees.amount1()))); assertEq(uint256(int256(delta.amount0())), uint256(int256(expectedFees.amount0()))); @@ -120,7 +120,7 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { vm.startPrank(alice); collect(tokenIdAlice, config, ZERO_BYTES); vm.stopPrank(); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); uint256 balance0AliceAfter = currency0.balanceOf(alice); uint256 balance1AliceAfter = currency1.balanceOf(alice); @@ -134,7 +134,7 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { vm.startPrank(bob); collect(tokenIdBob, config, ZERO_BYTES); vm.stopPrank(); - delta = snapLastDelta(); + delta = getLastDelta(); uint256 balance0BobAfter = currency0.balanceOf(bob); uint256 balance1BobAfter = currency1.balanceOf(bob); @@ -161,13 +161,13 @@ contract FeeCollectionTest is Test, PosmTestSetup, LiquidityFuzzers { vm.startPrank(alice); mint(config, liquidityAlice, alice, ZERO_BYTES); vm.stopPrank(); - BalanceDelta lpDeltaAlice = snapLastDelta(); + BalanceDelta lpDeltaAlice = getLastDelta(); uint256 tokenIdBob = lpm.nextTokenId(); vm.startPrank(bob); mint(config, liquidityBob, bob, ZERO_BYTES); vm.stopPrank(); - BalanceDelta lpDeltaBob = snapLastDelta(); + BalanceDelta lpDeltaBob = getLastDelta(); // swap to create fees uint256 swapAmount = 0.001e18; diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index 4438afbc..ff9ee598 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -84,7 +84,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { ); // add extra wei because modifyLiquidities may be rounding up, LiquidityAmounts is imprecise? lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); @@ -120,7 +120,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { // Mint with excess native tokens lpm.modifyLiquidities{value: amount0 * 2 + 1}(calls, _deadline); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); @@ -158,7 +158,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1BeforeBurn = currency1.balanceOfSelf(); decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); - BalanceDelta deltaDecrease = snapLastDelta(); + BalanceDelta deltaDecrease = getLastDelta(); uint256 deltasSnapsLength = hook.getDeltasLength(); burn(tokenId, config, ZERO_BYTES); @@ -211,7 +211,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1BeforeBurn = currency1.balanceOfSelf(); burn(tokenId, config, ZERO_BYTES); - BalanceDelta deltaBurn = snapLastDelta(); + BalanceDelta deltaBurn = getLastDelta(); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); assertEq(liquidity, 0); @@ -261,7 +261,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, ZERO_BYTES); // double the liquidity lpm.modifyLiquidities{value: amount0 + 1 wei}(calls, _deadline); // TODO: off by one wei - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); // verify position liquidity increased bytes32 positionId = @@ -303,7 +303,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { bytes memory calls = getIncreaseEncoded(tokenId, config, liquidityToAdd, ZERO_BYTES); // double the liquidity lpm.modifyLiquidities{value: amount0 * 2}(calls, _deadline); // overpay on increase liquidity - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); // verify position liquidity increased bytes32 positionId = @@ -343,7 +343,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint128(decreaseLiquidityDelta) ); decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); @@ -375,7 +375,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0Before = address(this).balance; uint256 balance1Before = currency1.balanceOfSelf(); collect(tokenId, config, ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); assertApproxEqAbs(currency0.balanceOfSelf() - balance0Before, feeRevenue0, 1 wei); // TODO: fuzzer off by 1 wei assertEq(currency0.balanceOfSelf() - balance0Before, uint128(delta.amount0())); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index f7b905bc..1d94938d 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -101,7 +101,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); mint(config, liquidityToAdd, address(this), ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); assertEq(tokenId, 1); assertEq(lpm.nextTokenId(), 2); @@ -136,7 +136,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 tokenId = lpm.nextTokenId(); mint(config, liquidityToAdd, address(this), ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); uint256 balance0After = currency0.balanceOfSelf(); uint256 balance1After = currency1.balanceOfSelf(); @@ -164,7 +164,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0BeforeAlice = currency0.balanceOf(alice); uint256 balance1BeforeAlice = currency1.balanceOf(alice); mint(config, liquidityToAdd, alice, ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); assertEq(tokenId, 1); assertEq(lpm.ownerOf(tokenId), alice); @@ -199,7 +199,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1BeforeBurn = currency1.balanceOfSelf(); decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); - BalanceDelta deltaDecrease = snapLastDelta(); + BalanceDelta deltaDecrease = getLastDelta(); uint256 deltasSnapsLength = hook.getDeltasLength(); // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. burn(tokenId, config, ZERO_BYTES); @@ -253,7 +253,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance1BeforeBurn = currency1.balanceOfSelf(); burn(tokenId, config, ZERO_BYTES); - BalanceDelta deltaBurn = snapLastDelta(); + BalanceDelta deltaBurn = getLastDelta(); assertEq(uint256(int256(deltaBurn.amount0())), amount0); assertEq(uint256(int256(deltaBurn.amount1())), amount1); @@ -316,7 +316,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 balance0Before = currency0.balanceOfSelf(); uint256 balance1Before = currency1.balanceOfSelf(); decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES); - BalanceDelta delta = snapLastDelta(); + BalanceDelta delta = getLastDelta(); bytes32 positionId = Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId)); diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index bf0f012b..ed8d8bd9 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -20,8 +20,6 @@ abstract contract LiquidityOperations is CommonBase { PositionManager lpm; - HookSavesDelta hook; - uint256 _deadline = block.timestamp + 1; function mint(PositionConfig memory config, uint256 liquidity, address recipient, bytes memory hookData) internal { @@ -134,8 +132,4 @@ abstract contract LiquidityOperations is CommonBase { // Close needed on burn in case there is liquidity left in the position. return planner.finalize(config.poolKey); } - - function snapLastDelta() internal view returns (BalanceDelta delta) { - delta = hook.deltas(hook.getDeltasLength() - 1); // just want the most recetly written to delta - } } diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index 1dae0bf0..f82a3173 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.24; import "forge-std/Test.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; @@ -19,6 +20,7 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { uint256 constant STARTING_USER_BALANCE = 10_000_000 ether; IAllowanceTransfer permit2; + HookSavesDelta hook; address hookAddr = address(uint160(Hooks.AFTER_ADD_LIQUIDITY_FLAG | Hooks.AFTER_REMOVE_LIQUIDITY_FLAG)); function deployPosmHookSavesDelta() public { @@ -62,4 +64,8 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { approvePosm(); vm.stopPrank(); } + + function getLastDelta() internal view returns (BalanceDelta delta) { + delta = hook.deltas(hook.getDeltasLength() - 1); // just want the most recetly written to delta + } } From 68859316c07a07b96c77825999d20828c939388e Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 10:25:31 -0400 Subject: [PATCH 13/23] rename --- src/PositionManager.sol | 1 + test/position-managers/Execute.t.sol | 4 +-- .../position-managers/IncreaseLiquidity.t.sol | 2 +- test/position-managers/NativeToken.t.sol | 4 +-- .../PositionManager.gas.t.sol | 34 +++++++++---------- .../PositionManager.multicall.t.sol | 2 +- test/position-managers/PositionManager.t.sol | 4 +-- test/shared/HookSavesDelta.sol | 2 +- test/shared/LiquidityOperations.sol | 10 +++--- test/shared/Planner.sol | 2 +- test/shared/PosmTestSetup.sol | 2 +- test/shared/fuzz/LiquidityFuzzers.sol | 2 +- 12 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 537851ab..f5970555 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -63,6 +63,7 @@ contract PositionManager is } /// @param unlockData is an encoding of actions, params, and currencies + /// @param deadline is the timestamp at which the unlockData will no longer be valid function modifyLiquidities(bytes calldata unlockData, uint256 deadline) external payable diff --git a/test/position-managers/Execute.t.sol b/test/position-managers/Execute.t.sol index 54d4f343..b745ec3a 100644 --- a/test/position-managers/Execute.t.sol +++ b/test/position-managers/Execute.t.sol @@ -89,7 +89,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd2, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); bytes32 positionId = @@ -111,7 +111,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers { planner.add(Actions.MINT_POSITION, abi.encode(config, initialLiquidity, address(this), ZERO_BYTES)); planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); bytes32 positionId = diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 554f48dc..2263757e 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -112,7 +112,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { // TODO: Can we make this easier to re-invest fees, so that you don't need to know the exact collect amount? Plan memory planner = Planner.init(); planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.startPrank(alice); lpm.modifyLiquidities(calls, _deadline); vm.stopPrank(); diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index ff9ee598..b702bb4f 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -160,10 +160,10 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); BalanceDelta deltaDecrease = getLastDelta(); - uint256 deltasSnapsLength = hook.getDeltasLength(); + uint256 deltasSnapsLength = hook.numberDeltasReturned(); burn(tokenId, config, ZERO_BYTES); // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. - assertEq(deltasSnapsLength, hook.getDeltasLength()); + assertEq(deltasSnapsLength, hook.numberDeltasReturned()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); assertEq(liquidity, 0); diff --git a/test/position-managers/PositionManager.gas.t.sol b/test/position-managers/PositionManager.gas.t.sol index 8670a2f2..a0c7244c 100644 --- a/test/position-managers/PositionManager.gas.t.sol +++ b/test/position-managers/PositionManager.gas.t.sol @@ -72,7 +72,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { function test_gas_mint() public { Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(this), ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_mint"); } @@ -86,7 +86,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { // Mint to a diff config, diff user. Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_mint_warmedPool_differentRange"); @@ -101,7 +101,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { // Mint to a diff config, diff user. Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_mint_onSameTickLower"); @@ -116,7 +116,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { // Mint to a diff config, diff user. Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_000 ether, address(alice), ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_mint_onSameTickUpper"); @@ -129,7 +129,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_increaseLiquidity_erc20"); } @@ -169,7 +169,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_increase_autocompoundExactUnclaimedFees"); @@ -210,7 +210,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenIdAlice, config, liquidityDelta, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); @@ -224,7 +224,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_decreaseLiquidity"); } @@ -244,7 +244,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); - bytes memory actions = planner.finalize(config.poolKey); + bytes memory actions = planner.finalizeModifyLiquidity(config.poolKey); calls[1] = abi.encodeWithSelector(IPositionManager.modifyLiquidities.selector, actions, _deadline); @@ -262,7 +262,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, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_collect"); } @@ -273,7 +273,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.MINT_POSITION, abi.encode(config, 10_001 ether, address(alice), ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); vm.prank(alice); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_mint_sameRange"); @@ -291,7 +291,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 10_000 ether, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_decrease_sameRange_allLiquidity"); } @@ -310,7 +310,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init().add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_collect_sameRange"); } @@ -320,7 +320,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { mint(config, 10_000 ether, address(this), ZERO_BYTES); Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_burn_nonEmpty"); @@ -350,7 +350,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, ZERO_BYTES)); // We must include CLOSE commands. - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_decrease_burnEmpty"); } @@ -432,7 +432,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { mintWithNative(SQRT_PRICE_1_1, configNative, 10_000 ether, address(this), ZERO_BYTES); Plan memory planner = Planner.init().add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); - bytes memory calls = planner.finalize(configNative.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(configNative.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_burn_nonEmpty_native"); @@ -462,7 +462,7 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { planner.add(Actions.BURN_POSITION, abi.encode(tokenId, configNative, ZERO_BYTES)); // We must include CLOSE commands. - bytes memory calls = planner.finalize(configNative.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(configNative.poolKey); lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_decrease_burnEmpty_native"); } diff --git a/test/position-managers/PositionManager.multicall.t.sol b/test/position-managers/PositionManager.multicall.t.sol index 1aaef5be..5dde4e17 100644 --- a/test/position-managers/PositionManager.multicall.t.sol +++ b/test/position-managers/PositionManager.multicall.t.sol @@ -56,7 +56,7 @@ contract PositionManagerMulticallTest is Test, PosmTestSetup, LiquidityFuzzers { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, 100e18, address(this), ZERO_BYTES)); - bytes memory actions = planner.finalize(config.poolKey); + bytes memory actions = planner.finalizeModifyLiquidity(config.poolKey); calls[1] = abi.encodeWithSelector(IPositionManager.modifyLiquidities.selector, actions, _deadline); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index 1d94938d..2d21af47 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -200,10 +200,10 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); BalanceDelta deltaDecrease = getLastDelta(); - uint256 deltasSnapsLength = hook.getDeltasLength(); + uint256 deltasSnapsLength = hook.numberDeltasReturned(); // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. burn(tokenId, config, ZERO_BYTES); - assertEq(deltasSnapsLength, hook.getDeltasLength()); + assertEq(deltasSnapsLength, hook.numberDeltasReturned()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); diff --git a/test/shared/HookSavesDelta.sol b/test/shared/HookSavesDelta.sol index 17c60cc8..e7cc833f 100644 --- a/test/shared/HookSavesDelta.sol +++ b/test/shared/HookSavesDelta.sol @@ -37,7 +37,7 @@ contract HookSavesDelta is BaseTestHooks { deltas.push(delta); } - function getDeltasLength() external view returns (uint256) { + function numberDeltasReturned() external view returns (uint256) { return deltas.length; } } diff --git a/test/shared/LiquidityOperations.sol b/test/shared/LiquidityOperations.sol index ed8d8bd9..433fa711 100644 --- a/test/shared/LiquidityOperations.sol +++ b/test/shared/LiquidityOperations.sol @@ -87,7 +87,7 @@ abstract contract LiquidityOperations is CommonBase { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidity, recipient, hookData)); - return planner.finalize(config.poolKey); + return planner.finalizeModifyLiquidity(config.poolKey); } function getIncreaseEncoded( @@ -98,7 +98,7 @@ abstract contract LiquidityOperations is CommonBase { ) internal pure returns (bytes memory) { Plan memory planner = Planner.init(); planner.add(Actions.INCREASE_LIQUIDITY, abi.encode(tokenId, config, liquidityToAdd, hookData)); - return planner.finalize(config.poolKey); + return planner.finalizeModifyLiquidity(config.poolKey); } function getDecreaseEncoded( @@ -109,7 +109,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, hookData)); - return planner.finalize(config.poolKey); + return planner.finalizeModifyLiquidity(config.poolKey); } function getCollectEncoded(uint256 tokenId, PositionConfig memory config, bytes memory hookData) @@ -119,7 +119,7 @@ abstract contract LiquidityOperations is CommonBase { { Plan memory planner = Planner.init(); planner.add(Actions.DECREASE_LIQUIDITY, abi.encode(tokenId, config, 0, hookData)); - return planner.finalize(config.poolKey); + return planner.finalizeModifyLiquidity(config.poolKey); } function getBurnEncoded(uint256 tokenId, PositionConfig memory config, bytes memory hookData) @@ -130,6 +130,6 @@ abstract contract LiquidityOperations is CommonBase { Plan memory planner = Planner.init(); planner.add(Actions.BURN_POSITION, abi.encode(tokenId, config, hookData)); // Close needed on burn in case there is liquidity left in the position. - return planner.finalize(config.poolKey); + return planner.finalizeModifyLiquidity(config.poolKey); } } diff --git a/test/shared/Planner.sol b/test/shared/Planner.sol index 4c019ae5..4bd0c1c9 100644 --- a/test/shared/Planner.sol +++ b/test/shared/Planner.sol @@ -38,7 +38,7 @@ library Planner { return plan; } - function finalize(Plan memory plan, PoolKey memory poolKey) internal pure returns (bytes memory) { + function finalizeModifyLiquidity(Plan memory plan, PoolKey memory poolKey) internal pure returns (bytes memory) { plan.add(Actions.CLOSE_CURRENCY, abi.encode(poolKey.currency0)); plan.add(Actions.CLOSE_CURRENCY, abi.encode(poolKey.currency1)); return plan.encode(); diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index f82a3173..dde3d9c6 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -66,6 +66,6 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { } function getLastDelta() internal view returns (BalanceDelta delta) { - delta = hook.deltas(hook.getDeltasLength() - 1); // just want the most recetly written to delta + delta = hook.deltas(hook.numberDeltasReturned() - 1); // just want the most recetly written to delta } } diff --git a/test/shared/fuzz/LiquidityFuzzers.sol b/test/shared/fuzz/LiquidityFuzzers.sol index bff8edde..fd73c1e2 100644 --- a/test/shared/fuzz/LiquidityFuzzers.sol +++ b/test/shared/fuzz/LiquidityFuzzers.sol @@ -31,7 +31,7 @@ contract LiquidityFuzzers is Fuzzers { Actions.MINT_POSITION, abi.encode(config, uint256(params.liquidityDelta), recipient, hookData) ); - bytes memory calls = planner.finalize(config.poolKey); + bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey); lpm.modifyLiquidities(calls, block.timestamp + 1); uint256 tokenId = lpm.nextTokenId() - 1; From a60f16d22e582649e302dcd8861b286359e918b2 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 10:26:11 -0400 Subject: [PATCH 14/23] comment --- test/position-managers/NativeToken.t.sol | 2 +- test/position-managers/PositionManager.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index b702bb4f..4fe113e8 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -162,7 +162,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { uint256 deltasSnapsLength = hook.numberDeltasReturned(); burn(tokenId, config, ZERO_BYTES); - // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. + // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length. assertEq(deltasSnapsLength, hook.numberDeltasReturned()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index 2d21af47..57a1ddde 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -201,7 +201,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); BalanceDelta deltaDecrease = getLastDelta(); uint256 deltasSnapsLength = hook.numberDeltasReturned(); - // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array with be the same length. + // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length. burn(tokenId, config, ZERO_BYTES); assertEq(deltasSnapsLength, hook.numberDeltasReturned()); From 7ac7043a52ef0f18e9071678ee56212fbde2db45 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 10:30:41 -0400 Subject: [PATCH 15/23] gas check --- src/PositionManager.sol | 2 +- test/position-managers/IncreaseLiquidity.t.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 6dc8e60e..870075cf 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -50,7 +50,7 @@ contract PositionManager is IAllowanceTransfer public immutable permit2; - uint256 public constant FULL_DELTA = type(uint256).max; + uint256 public constant FULL_DELTA = 0; constructor(IPoolManager _poolManager, IAllowanceTransfer _permit2) BaseActionsRouter(_poolManager) diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 81265850..d29f7119 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -344,8 +344,8 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, 0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, 0)); planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); From 64897c330c699a1d1cbc88ce5c9db21906cb2c89 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 10:33:54 -0400 Subject: [PATCH 16/23] add gas test, using uint256 --- ...nManager_mint_settleWithBalance_sweep.snap | 1 + src/PositionManager.sol | 2 +- .../position-managers/IncreaseLiquidity.t.sol | 4 ++-- .../PositionManager.gas.t.sol | 20 +++++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap diff --git a/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap new file mode 100644 index 00000000..cc4c8357 --- /dev/null +++ b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap @@ -0,0 +1 @@ +372637 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 870075cf..6dc8e60e 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -50,7 +50,7 @@ contract PositionManager is IAllowanceTransfer public immutable permit2; - uint256 public constant FULL_DELTA = 0; + uint256 public constant FULL_DELTA = type(uint256).max; constructor(IPoolManager _poolManager, IAllowanceTransfer _permit2) BaseActionsRouter(_poolManager) diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index d29f7119..81265850 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -344,8 +344,8 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, 0)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, 0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); diff --git a/test/position-managers/PositionManager.gas.t.sol b/test/position-managers/PositionManager.gas.t.sol index e6de3125..04d7f181 100644 --- a/test/position-managers/PositionManager.gas.t.sol +++ b/test/position-managers/PositionManager.gas.t.sol @@ -472,4 +472,24 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { lpm.modifyLiquidities(calls, _deadline); snapLastCall("PositionManager_decrease_burnEmpty_native"); } + + function test_gas_mint_settleWithBalance_sweep() public { + uint256 liquidityAlice = 3_000e18; + + Plan memory planner = Planner.init(); + planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); + planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); + planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); + + currency0.transfer(address(lpm), 100e18); + currency1.transfer(address(lpm), 100e18); + + bytes memory calls = planner.encode(); + + vm.prank(alice); + lpm.modifyLiquidities(calls, _deadline); + snapLastCall("PositionManager_mint_settleWithBalance_sweep"); + } } From b0b1b7321e55e689f0b24262f746db6c02e424c1 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 10:38:10 -0400 Subject: [PATCH 17/23] gas check, using 0 --- .../PositionManager_mint_settleWithBalance_sweep.snap | 2 +- src/PositionManager.sol | 9 +-------- src/interfaces/IPositionManager.sol | 1 - test/position-managers/IncreaseLiquidity.t.sol | 4 ++-- test/position-managers/PositionManager.gas.t.sol | 4 ++-- 5 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap index cc4c8357..93cbab28 100644 --- a/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap +++ b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap @@ -1 +1 @@ -372637 \ No newline at end of file +371867 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 6dc8e60e..6a0d069a 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -50,7 +50,7 @@ contract PositionManager is IAllowanceTransfer public immutable permit2; - uint256 public constant FULL_DELTA = type(uint256).max; + uint256 public constant FULL_DELTA = 0; constructor(IPoolManager _poolManager, IAllowanceTransfer _permit2) BaseActionsRouter(_poolManager) @@ -238,11 +238,4 @@ contract PositionManager is if (_amount > 0) revert IncorrectUseOfSettle(); amount = uint256(-_amount); } - - function _getFullTakeAmount(Currency currency) private view returns (uint256 amount) { - int256 _amount = poolManager.currencyDelta(address(this), currency); - // If the amount is negative, it should be settled not taken. - if (_amount < 0) revert IncorrectUseOfTake(); - amount = uint256(_amount); - } } diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index 7dc52fba..2aa3c957 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -6,7 +6,6 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; interface IPositionManager { error NotApproved(address caller); error DeadlinePassed(); - error IncorrectUseOfTake(); error IncorrectUseOfSettle(); error IncorrectPositionConfigForTokenId(uint256 tokenId); diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 81265850..d29f7119 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -344,8 +344,8 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, 0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, 0)); planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); diff --git a/test/position-managers/PositionManager.gas.t.sol b/test/position-managers/PositionManager.gas.t.sol index 04d7f181..2c88cbc1 100644 --- a/test/position-managers/PositionManager.gas.t.sol +++ b/test/position-managers/PositionManager.gas.t.sol @@ -478,8 +478,8 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, type(uint256).max)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, type(uint256).max)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, 0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, 0)); planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); From bdfc04de3854f84dcf4c93edc057853233ccf7d4 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 13:02:41 -0400 Subject: [PATCH 18/23] comments --- test/position-managers/NativeToken.t.sol | 4 ++-- test/position-managers/PositionManager.t.sol | 4 ++-- test/shared/PosmTestSetup.sol | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/position-managers/NativeToken.t.sol b/test/position-managers/NativeToken.t.sol index 4fe113e8..5c7a4592 100644 --- a/test/position-managers/NativeToken.t.sol +++ b/test/position-managers/NativeToken.t.sol @@ -160,10 +160,10 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); BalanceDelta deltaDecrease = getLastDelta(); - uint256 deltasSnapsLength = hook.numberDeltasReturned(); + uint256 numDeltas = hook.numberDeltasReturned(); burn(tokenId, config, ZERO_BYTES); // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length. - assertEq(deltasSnapsLength, hook.numberDeltasReturned()); + assertEq(numDeltas, hook.numberDeltasReturned()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); assertEq(liquidity, 0); diff --git a/test/position-managers/PositionManager.t.sol b/test/position-managers/PositionManager.t.sol index 57a1ddde..4309d870 100644 --- a/test/position-managers/PositionManager.t.sol +++ b/test/position-managers/PositionManager.t.sol @@ -200,10 +200,10 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers { decreaseLiquidity(tokenId, config, liquidity, ZERO_BYTES); BalanceDelta deltaDecrease = getLastDelta(); - uint256 deltasSnapsLength = hook.numberDeltasReturned(); + uint256 numDeltas = hook.numberDeltasReturned(); // No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length. burn(tokenId, config, ZERO_BYTES); - assertEq(deltasSnapsLength, hook.numberDeltasReturned()); + assertEq(numDeltas, hook.numberDeltasReturned()); (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); diff --git a/test/shared/PosmTestSetup.sol b/test/shared/PosmTestSetup.sol index dde3d9c6..1f945ccb 100644 --- a/test/shared/PosmTestSetup.sol +++ b/test/shared/PosmTestSetup.sol @@ -66,6 +66,6 @@ contract PosmTestSetup is Test, Deployers, DeployPermit2, LiquidityOperations { } function getLastDelta() internal view returns (BalanceDelta delta) { - delta = hook.deltas(hook.numberDeltasReturned() - 1); // just want the most recetly written to delta + delta = hook.deltas(hook.numberDeltasReturned() - 1); // just want the most recently written delta } } From 68e3a66ad85560e678681125492c915aef9869dd Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 13:14:36 -0400 Subject: [PATCH 19/23] remove SafeCallback --- src/PositionManager.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/PositionManager.sol b/src/PositionManager.sol index f5970555..f4cf09b8 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -16,7 +16,6 @@ import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol" import {ERC721Permit} from "./base/ERC721Permit.sol"; import {ReentrancyLock} from "./base/ReentrancyLock.sol"; import {IPositionManager} from "./interfaces/IPositionManager.sol"; -import {SafeCallback} from "./base/SafeCallback.sol"; import {Multicall} from "./base/Multicall.sol"; import {PoolInitializer} from "./base/PoolInitializer.sol"; import {DeltaResolver} from "./base/DeltaResolver.sol"; @@ -29,7 +28,6 @@ contract PositionManager is ERC721Permit, PoolInitializer, Multicall, - SafeCallback, DeltaResolver, ReentrancyLock, BaseActionsRouter From 07781300b9339c86f800623237027a8788f1e03e Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 13:32:49 -0400 Subject: [PATCH 20/23] remove FULL_DELTA --- .forge-snapshots/PositionManager_burn_empty.snap | 2 +- .../PositionManager_burn_empty_native.snap | 2 +- .forge-snapshots/PositionManager_burn_nonEmpty.snap | 2 +- .../PositionManager_burn_nonEmpty_native.snap | 2 +- .forge-snapshots/PositionManager_collect.snap | 2 +- .forge-snapshots/PositionManager_collect_native.snap | 2 +- .../PositionManager_collect_sameRange.snap | 2 +- .../PositionManager_decreaseLiquidity.snap | 2 +- .../PositionManager_decreaseLiquidity_native.snap | 2 +- .../PositionManager_decrease_burnEmpty.snap | 2 +- .../PositionManager_decrease_burnEmpty_native.snap | 2 +- ...sitionManager_decrease_sameRange_allLiquidity.snap | 2 +- .../PositionManager_increaseLiquidity_erc20.snap | 2 +- .../PositionManager_increaseLiquidity_native.snap | 2 +- ...nager_increase_autocompoundExactUnclaimedFees.snap | 2 +- ...Manager_increase_autocompoundExcessFeesCredit.snap | 2 +- .forge-snapshots/PositionManager_mint.snap | 2 +- .forge-snapshots/PositionManager_mint_native.snap | 2 +- .../PositionManager_mint_nativeWithSweep.snap | 2 +- .../PositionManager_mint_onSameTickLower.snap | 2 +- .../PositionManager_mint_onSameTickUpper.snap | 2 +- .forge-snapshots/PositionManager_mint_sameRange.snap | 2 +- .../PositionManager_mint_settleWithBalance_sweep.snap | 2 +- ...ositionManager_mint_warmedPool_differentRange.snap | 2 +- .../PositionManager_multicall_initialize_mint.snap | 2 +- src/PositionManager.sol | 11 +++-------- test/position-managers/IncreaseLiquidity.t.sol | 4 ++-- test/position-managers/PositionManager.gas.t.sol | 4 ++-- 28 files changed, 32 insertions(+), 37 deletions(-) diff --git a/.forge-snapshots/PositionManager_burn_empty.snap b/.forge-snapshots/PositionManager_burn_empty.snap index f78f7047..2758ccf3 100644 --- a/.forge-snapshots/PositionManager_burn_empty.snap +++ b/.forge-snapshots/PositionManager_burn_empty.snap @@ -1 +1 @@ -47289 \ No newline at end of file +47271 \ 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 ae19082c..462cc207 100644 --- a/.forge-snapshots/PositionManager_burn_empty_native.snap +++ b/.forge-snapshots/PositionManager_burn_empty_native.snap @@ -1 +1 @@ -47107 \ No newline at end of file +47088 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty.snap b/.forge-snapshots/PositionManager_burn_nonEmpty.snap index 71a89bba..d1f6268f 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty.snap @@ -1 +1 @@ -130157 \ No newline at end of file +130139 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap index 0f249c54..cd0f3868 100644 --- a/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap +++ b/.forge-snapshots/PositionManager_burn_nonEmpty_native.snap @@ -1 +1 @@ -123079 \ No newline at end of file +123060 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect.snap b/.forge-snapshots/PositionManager_collect.snap index b0632faa..0c61cc2c 100644 --- a/.forge-snapshots/PositionManager_collect.snap +++ b/.forge-snapshots/PositionManager_collect.snap @@ -1 +1 @@ -151246 \ No newline at end of file +151223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_native.snap b/.forge-snapshots/PositionManager_collect_native.snap index ead911d3..3767f77c 100644 --- a/.forge-snapshots/PositionManager_collect_native.snap +++ b/.forge-snapshots/PositionManager_collect_native.snap @@ -1 +1 @@ -142398 \ No newline at end of file +142375 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_collect_sameRange.snap b/.forge-snapshots/PositionManager_collect_sameRange.snap index b0632faa..0c61cc2c 100644 --- a/.forge-snapshots/PositionManager_collect_sameRange.snap +++ b/.forge-snapshots/PositionManager_collect_sameRange.snap @@ -1 +1 @@ -151246 \ No newline at end of file +151223 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity.snap b/.forge-snapshots/PositionManager_decreaseLiquidity.snap index b4ccbaf8..f7274df9 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity.snap @@ -1 +1 @@ -116789 \ No newline at end of file +116766 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap index daa51173..8ef6aa1f 100644 --- a/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_decreaseLiquidity_native.snap @@ -1 +1 @@ -109393 \ No newline at end of file +109375 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap index 2875746c..31fc4741 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty.snap @@ -1 +1 @@ -135196 \ No newline at end of file +135178 \ 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 67d16579..4be6bbf3 100644 --- a/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap +++ b/.forge-snapshots/PositionManager_decrease_burnEmpty_native.snap @@ -1 +1 @@ -127936 \ No newline at end of file +127917 \ 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 40053a2e..28c9ff85 100644 --- a/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap +++ b/.forge-snapshots/PositionManager_decrease_sameRange_allLiquidity.snap @@ -1 +1 @@ -129505 \ No newline at end of file +129482 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap index a7513752..d9432f54 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_erc20.snap @@ -1 +1 @@ -152759 \ No newline at end of file +152736 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap index 5a45fec3..52783d26 100644 --- a/.forge-snapshots/PositionManager_increaseLiquidity_native.snap +++ b/.forge-snapshots/PositionManager_increaseLiquidity_native.snap @@ -1 +1 @@ -134559 \ No newline at end of file +134536 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap index 6f6a89bc..32633ab4 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExactUnclaimedFees.snap @@ -1 +1 @@ -135455 \ No newline at end of file +135432 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap index dcd442a1..c6e7ab8c 100644 --- a/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap +++ b/.forge-snapshots/PositionManager_increase_autocompoundExcessFeesCredit.snap @@ -1 +1 @@ -171611 \ No newline at end of file +171588 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint.snap b/.forge-snapshots/PositionManager_mint.snap index 4bea99ea..23cba396 100644 --- a/.forge-snapshots/PositionManager_mint.snap +++ b/.forge-snapshots/PositionManager_mint.snap @@ -1 +1 @@ -372860 \ No newline at end of file +372837 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_native.snap b/.forge-snapshots/PositionManager_mint_native.snap index 7eb96e43..85caa484 100644 --- a/.forge-snapshots/PositionManager_mint_native.snap +++ b/.forge-snapshots/PositionManager_mint_native.snap @@ -1 +1 @@ -337560 \ No newline at end of file +337537 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap index 21b76907..7b0eabb1 100644 --- a/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap +++ b/.forge-snapshots/PositionManager_mint_nativeWithSweep.snap @@ -1 +1 @@ -346422 \ No newline at end of file +346399 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap index 17a33e04..7886fb4f 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickLower.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickLower.snap @@ -1 +1 @@ -315542 \ No newline at end of file +315519 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap index a070ee97..2380e1a5 100644 --- a/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap +++ b/.forge-snapshots/PositionManager_mint_onSameTickUpper.snap @@ -1 +1 @@ -316184 \ No newline at end of file +316161 \ No newline at end of file diff --git a/.forge-snapshots/PositionManager_mint_sameRange.snap b/.forge-snapshots/PositionManager_mint_sameRange.snap index af9d354d..b1fa5dd3 100644 --- a/.forge-snapshots/PositionManager_mint_sameRange.snap +++ b/.forge-snapshots/PositionManager_mint_sameRange.snap @@ -1 +1 @@ -241766 \ No newline at end of file +241743 \ 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 a55a721f..e9566d58 100644 --- a/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap +++ b/.forge-snapshots/PositionManager_mint_settleWithBalance_sweep.snap @@ -1 +1 @@ -371915 \ No newline at end of file +371451 \ 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 1b045bab..c470bf98 100644 --- a/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap +++ b/.forge-snapshots/PositionManager_mint_warmedPool_differentRange.snap @@ -1 +1 @@ -321560 \ No newline at end of file +321537 \ 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 dfdf5bb4..187c5c91 100644 --- a/.forge-snapshots/PositionManager_multicall_initialize_mint.snap +++ b/.forge-snapshots/PositionManager_multicall_initialize_mint.snap @@ -1 +1 @@ -417240 \ No newline at end of file +417173 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index ef9b4a1c..f1538dbb 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -48,8 +48,6 @@ contract PositionManager is IAllowanceTransfer public immutable permit2; - uint256 public constant FULL_DELTA = 0; - constructor(IPoolManager _poolManager, IAllowanceTransfer _permit2) BaseActionsRouter(_poolManager) ERC721Permit("Uniswap V4 Positions NFT", "UNI-V4-POSM", "1") @@ -157,16 +155,13 @@ contract PositionManager is } } - /// @param params is an encoding of Currency, uint256 amount - /// @dev if amount == FULL_DELTA, it settles the full negative delta + /// @param params is an encoding of Currency /// @dev uses this addresses balance to settle a negative delta function _settleWithBalance(bytes memory params) internal { - (Currency currency, uint256 amount) = abi.decode(params, (Currency, uint256)); - - amount = amount == FULL_DELTA ? _getFullSettleAmount(currency) : amount; + Currency currency = abi.decode(params, (Currency)); // set the payer to this address, performs a transfer. - _settle(currency, address(this), amount); + _settle(currency, address(this), _getFullSettleAmount(currency)); } /// @param params is an encoding of uint256 tokenId, PositionConfig memory config, bytes hookData diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 53fd1d46..27a880b2 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -344,8 +344,8 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, 0)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, 0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1)); planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); diff --git a/test/position-managers/PositionManager.gas.t.sol b/test/position-managers/PositionManager.gas.t.sol index 3bbb86dd..c5a44d41 100644 --- a/test/position-managers/PositionManager.gas.t.sol +++ b/test/position-managers/PositionManager.gas.t.sol @@ -478,8 +478,8 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot { Plan memory planner = Planner.init(); planner.add(Actions.MINT_POSITION, abi.encode(config, liquidityAlice, alice, ZERO_BYTES)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0, 0)); - planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1, 0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1)); planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); From 03e978f454a142ea96d831325d6b1ec7a099ad91 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 17:03:50 -0400 Subject: [PATCH 21/23] move helpers to delta resolver --- .forge-snapshots/V4Router_Bytecode.snap | 2 +- .../V4Router_ExactIn1Hop_nativeIn.snap | 2 +- .../V4Router_ExactIn1Hop_nativeOut.snap | 2 +- .../V4Router_ExactIn1Hop_oneForZero.snap | 2 +- .../V4Router_ExactIn1Hop_zeroForOne.snap | 2 +- .forge-snapshots/V4Router_ExactIn2Hops.snap | 2 +- .../V4Router_ExactIn2Hops_nativeIn.snap | 2 +- .forge-snapshots/V4Router_ExactIn3Hops.snap | 2 +- .../V4Router_ExactIn3Hops_nativeIn.snap | 2 +- .../V4Router_ExactInputSingle.snap | 2 +- .../V4Router_ExactInputSingle_nativeIn.snap | 2 +- .../V4Router_ExactInputSingle_nativeOut.snap | 2 +- ...Router_ExactOut1Hop_nativeIn_sweepETH.snap | 2 +- .../V4Router_ExactOut1Hop_nativeOut.snap | 2 +- .../V4Router_ExactOut1Hop_oneForZero.snap | 2 +- .../V4Router_ExactOut1Hop_zeroForOne.snap | 2 +- .forge-snapshots/V4Router_ExactOut2Hops.snap | 2 +- .../V4Router_ExactOut2Hops_nativeIn.snap | 2 +- .forge-snapshots/V4Router_ExactOut3Hops.snap | 2 +- .../V4Router_ExactOut3Hops_nativeIn.snap | 2 +- .../V4Router_ExactOut3Hops_nativeOut.snap | 2 +- .../V4Router_ExactOutputSingle.snap | 2 +- ...r_ExactOutputSingle_nativeIn_sweepETH.snap | 2 +- .../V4Router_ExactOutputSingle_nativeOut.snap | 2 +- src/PositionManager.sol | 7 ------ src/V4Router.sol | 10 ++++---- src/base/DeltaResolver.sol | 24 +++++++++++++++++-- src/interfaces/IPositionManager.sol | 1 - 28 files changed, 50 insertions(+), 40 deletions(-) diff --git a/.forge-snapshots/V4Router_Bytecode.snap b/.forge-snapshots/V4Router_Bytecode.snap index e11616e3..42bd3cdc 100644 --- a/.forge-snapshots/V4Router_Bytecode.snap +++ b/.forge-snapshots/V4Router_Bytecode.snap @@ -1 +1 @@ -6595 \ No newline at end of file +6628 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_nativeIn.snap b/.forge-snapshots/V4Router_ExactIn1Hop_nativeIn.snap index f6f8b33c..24c9822b 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_nativeIn.snap @@ -1 +1 @@ -120991 \ No newline at end of file +121090 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap b/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap index 0a624153..24ccfd9d 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_nativeOut.snap @@ -1 +1 @@ -120158 \ No newline at end of file +120257 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap b/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap index 6f2f9ce5..f891c6dd 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_oneForZero.snap @@ -1 +1 @@ -129030 \ No newline at end of file +129129 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap b/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap index 612b68dd..f6834076 100644 --- a/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap +++ b/.forge-snapshots/V4Router_ExactIn1Hop_zeroForOne.snap @@ -1 +1 @@ -135860 \ No newline at end of file +135959 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn2Hops.snap b/.forge-snapshots/V4Router_ExactIn2Hops.snap index 8eb82f04..e70fa136 100644 --- a/.forge-snapshots/V4Router_ExactIn2Hops.snap +++ b/.forge-snapshots/V4Router_ExactIn2Hops.snap @@ -1 +1 @@ -187212 \ No newline at end of file +187311 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn2Hops_nativeIn.snap b/.forge-snapshots/V4Router_ExactIn2Hops_nativeIn.snap index c14560ee..69edacf1 100644 --- a/.forge-snapshots/V4Router_ExactIn2Hops_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactIn2Hops_nativeIn.snap @@ -1 +1 @@ -179175 \ No newline at end of file +179274 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn3Hops.snap b/.forge-snapshots/V4Router_ExactIn3Hops.snap index 0409f93c..6de237e2 100644 --- a/.forge-snapshots/V4Router_ExactIn3Hops.snap +++ b/.forge-snapshots/V4Router_ExactIn3Hops.snap @@ -1 +1 @@ -238593 \ No newline at end of file +238692 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactIn3Hops_nativeIn.snap b/.forge-snapshots/V4Router_ExactIn3Hops_nativeIn.snap index 913a30c6..33ade7d1 100644 --- a/.forge-snapshots/V4Router_ExactIn3Hops_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactIn3Hops_nativeIn.snap @@ -1 +1 @@ -230580 \ No newline at end of file +230679 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactInputSingle.snap b/.forge-snapshots/V4Router_ExactInputSingle.snap index af44576c..2e3423fd 100644 --- a/.forge-snapshots/V4Router_ExactInputSingle.snap +++ b/.forge-snapshots/V4Router_ExactInputSingle.snap @@ -1 +1 @@ -134618 \ No newline at end of file +134717 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactInputSingle_nativeIn.snap b/.forge-snapshots/V4Router_ExactInputSingle_nativeIn.snap index c73f471b..b7011dc2 100644 --- a/.forge-snapshots/V4Router_ExactInputSingle_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactInputSingle_nativeIn.snap @@ -1 +1 @@ -119749 \ No newline at end of file +119848 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap b/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap index c2705e54..cdff580e 100644 --- a/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactInputSingle_nativeOut.snap @@ -1 +1 @@ -118894 \ No newline at end of file +118993 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap b/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap index 05f02403..77e59bce 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_nativeIn_sweepETH.snap @@ -1 +1 @@ -126794 \ No newline at end of file +126893 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap b/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap index cd9382b3..f276517c 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_nativeOut.snap @@ -1 +1 @@ -120999 \ No newline at end of file +121098 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap b/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap index 1d29c498..efacec37 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_oneForZero.snap @@ -1 +1 @@ -129871 \ No newline at end of file +129970 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap b/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap index d1018c3e..bd7e8a65 100644 --- a/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap +++ b/.forge-snapshots/V4Router_ExactOut1Hop_zeroForOne.snap @@ -1 +1 @@ -134672 \ No newline at end of file +134771 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut2Hops.snap b/.forge-snapshots/V4Router_ExactOut2Hops.snap index 3ecc5f00..be849ee5 100644 --- a/.forge-snapshots/V4Router_ExactOut2Hops.snap +++ b/.forge-snapshots/V4Router_ExactOut2Hops.snap @@ -1 +1 @@ -186633 \ No newline at end of file +186732 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap b/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap index a76127c1..1ae42da1 100644 --- a/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactOut2Hops_nativeIn.snap @@ -1 +1 @@ -183556 \ No newline at end of file +183655 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops.snap b/.forge-snapshots/V4Router_ExactOut3Hops.snap index 45e158a2..9883a932 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops.snap @@ -1 +1 @@ -238638 \ No newline at end of file +238737 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap b/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap index 7cba59fe..f55c5a60 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops_nativeIn.snap @@ -1 +1 @@ -235585 \ No newline at end of file +235684 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap b/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap index 72b7d53b..4301df86 100644 --- a/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOut3Hops_nativeOut.snap @@ -1 +1 @@ -229790 \ No newline at end of file +229889 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle.snap b/.forge-snapshots/V4Router_ExactOutputSingle.snap index a538db14..ef03db55 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle.snap @@ -1 +1 @@ -133152 \ No newline at end of file +133251 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap b/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap index baf2e400..d3168270 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle_nativeIn_sweepETH.snap @@ -1 +1 @@ -125274 \ No newline at end of file +125373 \ No newline at end of file diff --git a/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap b/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap index 8cf4fc55..78729eea 100644 --- a/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap +++ b/.forge-snapshots/V4Router_ExactOutputSingle_nativeOut.snap @@ -1 +1 @@ -119537 \ No newline at end of file +119636 \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index f1538dbb..7e057aca 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -229,11 +229,4 @@ contract PositionManager is permit2.transferFrom(payer, address(poolManager), uint160(amount), Currency.unwrap(currency)); } } - - function _getFullSettleAmount(Currency currency) private view returns (uint256 amount) { - int256 _amount = poolManager.currencyDelta(address(this), currency); - // If the amount is positive, it should be taken not settled for. - if (_amount > 0) revert IncorrectUseOfSettle(); - amount = uint256(-_amount); - } } diff --git a/src/V4Router.sol b/src/V4Router.sol index 5e7e81ab..b14b01c5 100644 --- a/src/V4Router.sol +++ b/src/V4Router.sol @@ -51,12 +51,11 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver { currency := calldataload(params.offset) } - int256 delta = poolManager.currencyDelta(address(this), currency); - if (delta > 0) revert InvalidDeltaForAction(); + uint256 amount = _getFullSettleAmount(currency); // TODO support address(this) paying too // TODO should it have a maxAmountOut added slippage protection? - _settle(currency, _msgSender(), uint256(-delta)); + _settle(currency, _msgSender(), amount); } else if (action == Actions.TAKE_ALL) { // equivalent: abi.decode(params, (Currency, address)) Currency currency; @@ -66,12 +65,11 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver { recipient := calldataload(add(params.offset, 0x20)) } - int256 delta = poolManager.currencyDelta(address(this), currency); - if (delta < 0) revert InvalidDeltaForAction(); + uint256 amount = _getFullTakeAmount(currency); // TODO should _take have a minAmountOut added slippage check? // TODO recipient mapping - _take(currency, recipient, uint256(delta)); + _take(currency, recipient, amount); } else { revert UnsupportedAction(action); } diff --git a/src/base/DeltaResolver.sol b/src/base/DeltaResolver.sol index e67721cc..9ddd81db 100644 --- a/src/base/DeltaResolver.sol +++ b/src/base/DeltaResolver.sol @@ -2,13 +2,19 @@ pragma solidity ^0.8.24; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; +import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol"; +import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {ImmutableState} from "./ImmutableState.sol"; /// @notice Abstract contract used to sync, send, and settle funds to the pool manager /// @dev Note that sync() is called before any erc-20 transfer in `settle`. abstract contract DeltaResolver is ImmutableState { - /// @notice Emitted trying to settle a positive delta, or take a negative delta - error InvalidDeltaForAction(); + using TransientStateLibrary for IPoolManager; + + /// @notice Emitted trying to settle a positive delta. + error IncorrectUseOfSettle(); + /// @notice Emitted trying to take a negative delta. + error IncorrectUseOfTake(); /// @notice Take an amount of currency out of the PoolManager /// @param currency Currency to take @@ -39,4 +45,18 @@ abstract contract DeltaResolver is ImmutableState { /// @param payer The address who should pay tokens /// @param amount The number of tokens to send function _pay(Currency token, address payer, uint256 amount) internal virtual; + + function _getFullSettleAmount(Currency currency) internal view returns (uint256 amount) { + int256 _amount = poolManager.currencyDelta(address(this), currency); + // If the amount is positive, it should be taken not settled for. + if (_amount > 0) revert IncorrectUseOfSettle(); + amount = uint256(-_amount); + } + + function _getFullTakeAmount(Currency currency) internal view returns (uint256 amount) { + int256 _amount = poolManager.currencyDelta(address(this), currency); + // If the amount is negative, it should be settled not taken. + if (_amount < 0) revert IncorrectUseOfTake(); + amount = uint256(_amount); + } } diff --git a/src/interfaces/IPositionManager.sol b/src/interfaces/IPositionManager.sol index 2aa3c957..ebf0b482 100644 --- a/src/interfaces/IPositionManager.sol +++ b/src/interfaces/IPositionManager.sol @@ -6,7 +6,6 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; interface IPositionManager { error NotApproved(address caller); error DeadlinePassed(); - error IncorrectUseOfSettle(); error IncorrectPositionConfigForTokenId(uint256 tokenId); /// @notice Maps the ERC721 tokenId to a configId, which is a keccak256 hash of the position's pool key, and range (tickLower, tickUpper) From dedf3101cac0e848dc09dcf169b9c5482764f639 Mon Sep 17 00:00:00 2001 From: Sara Reynolds Date: Tue, 30 Jul 2024 17:26:02 -0400 Subject: [PATCH 22/23] remove import --- src/V4Router.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/V4Router.sol b/src/V4Router.sol index b14b01c5..1b264f72 100644 --- a/src/V4Router.sol +++ b/src/V4Router.sol @@ -6,7 +6,6 @@ import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol"; import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; -import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol"; import {PathKey, PathKeyLib} from "./libraries/PathKey.sol"; import {CalldataDecoder} from "./libraries/CalldataDecoder.sol"; @@ -24,7 +23,6 @@ abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver { using SafeCast for *; using PathKeyLib for PathKey; using CalldataDecoder for bytes; - using TransientStateLibrary for IPoolManager; constructor(IPoolManager _poolManager) BaseActionsRouter(_poolManager) {} From 428db01ce4dfdd960a088c9e115f6e456890eeb8 Mon Sep 17 00:00:00 2001 From: Alice Henshaw Date: Wed, 31 Jul 2024 12:22:54 +0100 Subject: [PATCH 23/23] increase liq with sttle with balance test --- src/libraries/Actions.sol | 40 +++++++------- .../position-managers/IncreaseLiquidity.t.sol | 55 ++++++++++++++++++- 2 files changed, 74 insertions(+), 21 deletions(-) diff --git a/src/libraries/Actions.sol b/src/libraries/Actions.sol index 9c5ccfc7..132fde68 100644 --- a/src/libraries/Actions.sol +++ b/src/libraries/Actions.sol @@ -5,35 +5,35 @@ pragma solidity ^0.8.24; /// @dev These are suggested common commands, however additional commands should be defined as required library Actions { // pool actions + // liquidity actions uint256 constant INCREASE_LIQUIDITY = 0x00; uint256 constant DECREASE_LIQUIDITY = 0x01; - uint256 constant SWAP_EXACT_IN_SINGLE = 0x02; - uint256 constant SWAP_EXACT_IN = 0x03; - uint256 constant SWAP_EXACT_OUT_SINGLE = 0x04; - uint256 constant SWAP_EXACT_OUT = 0x05; - uint256 constant DONATE = 0x06; + uint256 constant MINT_POSITION = 0x02; + uint256 constant BURN_POSITION = 0x03; + // swapping + uint256 constant SWAP_EXACT_IN_SINGLE = 0x04; + uint256 constant SWAP_EXACT_IN = 0x05; + uint256 constant SWAP_EXACT_OUT_SINGLE = 0x06; + uint256 constant SWAP_EXACT_OUT = 0x07; + // donate + uint256 constant DONATE = 0x08; // closing deltas on the pool manager + // settling uint256 constant SETTLE = 0x10; uint256 constant SETTLE_ALL = 0x11; + uint256 constant SETTLE_WITH_BALANCE = 0x12; + // taking + uint256 constant TAKE = 0x13; + uint256 constant TAKE_ALL = 0x14; + uint256 constant TAKE_PORTION = 0x15; - uint256 constant TAKE = 0x12; - uint256 constant TAKE_ALL = 0x13; - uint256 constant TAKE_PORTION = 0x14; - - uint256 constant CLOSE_CURRENCY = 0x15; - uint256 constant CLOSE_PAIR = 0x16; - uint256 constant CLEAR = 0x17; + uint256 constant CLOSE_CURRENCY = 0x16; + uint256 constant CLOSE_PAIR = 0x17; + uint256 constant CLEAR = 0x18; + uint256 constant SWEEP = 0x19; // minting/burning 6909s to close deltas uint256 constant MINT_6909 = 0x20; uint256 constant BURN_6909 = 0x21; - - // mint + burn ERC721 position - uint256 constant MINT_POSITION = 0x22; - uint256 constant BURN_POSITION = 0x23; - - // settle using the balance contract - uint256 constant SETTLE_WITH_BALANCE = 0x24; - uint256 constant SWEEP = 0x25; } diff --git a/test/position-managers/IncreaseLiquidity.t.sol b/test/position-managers/IncreaseLiquidity.t.sol index 27a880b2..4e01b238 100644 --- a/test/position-managers/IncreaseLiquidity.t.sol +++ b/test/position-managers/IncreaseLiquidity.t.sol @@ -13,8 +13,8 @@ import {LiquidityAmounts} from "@uniswap/v4-core/test/utils/LiquidityAmounts.sol import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol"; -import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {Fuzzers} from "@uniswap/v4-core/src/test/Fuzzers.sol"; +import {Position} from "@uniswap/v4-core/src/libraries/Position.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; @@ -32,6 +32,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { using PoolIdLibrary for PoolKey; using Planner for Plan; using FeeMath for IPositionManager; + using StateLibrary for IPoolManager; PoolId poolId; address alice = makeAddr("ALICE"); @@ -376,4 +377,56 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers { assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amount0); assertEq(currency1.balanceOf(address(this)), balanceBefore1 - amount1); } + + function test_increaseLiquidity_settleWithBalance() public { + uint256 liquidityAlice = 3_000e18; + + // alice provides liquidity + vm.prank(alice); + mint(config, liquidityAlice, alice, ZERO_BYTES); + uint256 tokenIdAlice = lpm.nextTokenId() - 1; + + bytes32 positionId = + Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenIdAlice)); + (uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); + 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, ZERO_BYTES)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency0)); + planner.add(Actions.SETTLE_WITH_BALANCE, abi.encode(currency1)); + planner.add(Actions.SWEEP, abi.encode(currency0, address(this))); + planner.add(Actions.SWEEP, abi.encode(currency1, address(this))); + + uint256 balanceBefore0 = currency0.balanceOf(address(this)); + uint256 balanceBefore1 = currency1.balanceOf(address(this)); + + assertEq(currency0.balanceOf(address(lpm)), 0); + assertEq(currency0.balanceOf(address(lpm)), 0); + + currency0.transfer(address(lpm), 100e18); + currency1.transfer(address(lpm), 100e18); + + assertEq(currency0.balanceOf(address(lpm)), 100e18); + assertEq(currency0.balanceOf(address(lpm)), 100e18); + + bytes memory calls = planner.encode(); + + vm.prank(alice); + lpm.modifyLiquidities(calls, _deadline); + BalanceDelta delta = getLastDelta(); + uint256 amount0 = uint128(-delta.amount0()); + uint256 amount1 = uint128(-delta.amount1()); + + (liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId); + assertEq(liquidity, 2 * liquidityAlice); + + // The balances were swept back to this address. + assertEq(IERC20(Currency.unwrap(currency0)).balanceOf(address(lpm)), 0); + assertEq(IERC20(Currency.unwrap(currency1)).balanceOf(address(lpm)), 0); + + assertEq(currency0.balanceOf(address(this)), balanceBefore0 - amount0); + assertEq(currency1.balanceOf(address(this)), balanceBefore1 - amount1); + } }