Skip to content

Commit

Permalink
add posm view lib
Browse files Browse the repository at this point in the history
  • Loading branch information
snreynolds committed Aug 1, 2024
1 parent f38a66f commit 5d815cd
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 97 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_burn_empty.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
46761
46857
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_burn_empty_native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
46579
46675
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_burn_nonEmpty.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
129621
129716
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_burn_nonEmpty_native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
122543
122638
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_decrease_burnEmpty.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
133487
133582
Original file line number Diff line number Diff line change
@@ -1 +1 @@
126226
126321
16 changes: 3 additions & 13 deletions src/PositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol";
import {Position} from "@uniswap/v4-core/src/libraries/Position.sol";
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol";
import {Position} from "@uniswap/v4-core/src/libraries/Position.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
Expand All @@ -25,6 +24,7 @@ import {PositionConfig, PositionConfigLibrary} from "./libraries/PositionConfig.
import {BaseActionsRouter} from "./base/BaseActionsRouter.sol";
import {Actions} from "./libraries/Actions.sol";
import {CalldataDecoder} from "./libraries/CalldataDecoder.sol";
import {PosmStateLibrary} from "./libraries/PosmStateLibrary.sol";

contract PositionManager is
IPositionManager,
Expand All @@ -39,7 +39,7 @@ contract PositionManager is
using CurrencyLibrary for Currency;
using PoolIdLibrary for PoolKey;
using PositionConfigLibrary for PositionConfig;
using StateLibrary for IPoolManager;
using PosmStateLibrary for IPoolManager;
using TransientStateLibrary for IPoolManager;
using SafeCast for uint256;
using CalldataDecoder for bytes;
Expand Down Expand Up @@ -171,7 +171,7 @@ contract PositionManager is
function _burn(uint256 tokenId, PositionConfig calldata config, bytes calldata hookData) internal {
if (!_isApprovedOrOwner(_msgSender(), tokenId)) revert NotApproved(_msgSender());
if (positionConfigs[tokenId] != config.toId()) revert IncorrectPositionConfigForTokenId(tokenId);
uint256 liquidity = uint256(_getPositionLiquidity(config, tokenId));
uint256 liquidity = poolManager.getPositionLiquidity(tokenId, config);

BalanceDelta liquidityDelta;
// Can only call modify if there is non zero liquidity.
Expand Down Expand Up @@ -202,16 +202,6 @@ contract PositionManager is
);
}

function _getPositionLiquidity(PositionConfig calldata config, uint256 tokenId)
internal
view
returns (uint128 liquidity)
{
bytes32 positionId =
Position.calculatePositionKey(address(this), config.tickLower, config.tickUpper, bytes32(tokenId));
liquidity = poolManager.getPositionLiquidity(config.poolKey.toId(), positionId);
}

/// @notice Sweeps the entire contract balance of specified currency to the recipient
function _sweep(Currency currency, address to) internal {
uint256 balance = currency.balanceOfSelf();
Expand Down
26 changes: 26 additions & 0 deletions src/libraries/PosmStateLibrary.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.24;

import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import {Position} from "@uniswap/v4-core/src/libraries/Position.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";

import {PositionConfig} from "./PositionConfig.sol";

/// @notice A library for reading POSM specific information from core, wraps core's StateLibrary
library PosmStateLibrary {
using StateLibrary for IPoolManager;
using PoolIdLibrary for PoolKey;

function getPositionLiquidity(IPoolManager poolManager, uint256 tokenId, PositionConfig memory config)
internal
view
returns (uint128 liquidity)
{
bytes32 positionId =
Position.calculatePositionKey(address(this), config.tickLower, config.tickUpper, bytes32(tokenId));
liquidity = poolManager.getPositionLiquidity(config.poolKey.toId(), positionId);
}
}
23 changes: 5 additions & 18 deletions test/position-managers/Execute.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {LiquidityAmounts} from "@uniswap/v4-core/test/utils/LiquidityAmounts.sol";
import {Position} from "@uniswap/v4-core/src/libraries/Position.sol";
Expand All @@ -31,7 +30,6 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers {
using CurrencyLibrary for Currency;
using PoolIdLibrary for PoolKey;
using Planner for Plan;
using StateLibrary for IPoolManager;

PoolId poolId;
address alice = makeAddr("ALICE");
Expand Down Expand Up @@ -71,9 +69,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers {

increaseLiquidity(tokenId, config, liquidityToAdd, ZERO_BYTES);

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);

assertEq(liquidity, initialLiquidity + liquidityToAdd);
}
Expand All @@ -97,9 +93,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers {
bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey);
lpm.modifyLiquidities(calls, _deadline);

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);

assertEq(liquidity, initialLiquidity + liquidityToAdd + liquidityToAdd2);
}
Expand All @@ -119,9 +113,7 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers {
bytes memory calls = planner.finalizeModifyLiquidity(config.poolKey);
lpm.modifyLiquidities(calls, _deadline);

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);

assertEq(liquidity, initialLiquidity + liquidityToAdd);
}
Expand Down Expand Up @@ -175,20 +167,15 @@ contract ExecuteTest is Test, PosmTestSetup, LiquidityFuzzers {

{
// old position has no liquidity
bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
uint128 liquidity = manager.getPositionLiquidity(config.poolKey.toId(), positionId);
uint128 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, 0);

// new token was minted
uint256 newTokenId = lpm.nextTokenId() - 1;
assertEq(lpm.ownerOf(newTokenId), address(this));

// new token has expected liquidity
positionId = Position.calculatePositionKey(
address(lpm), newConfig.tickLower, newConfig.tickUpper, bytes32(newTokenId)
);
liquidity = manager.getPositionLiquidity(config.poolKey.toId(), positionId);
liquidity = _getPositionLiquidity(newTokenId, newConfig);
assertEq(liquidity, newLiquidity);
}
}
Expand Down
12 changes: 4 additions & 8 deletions test/position-managers/IncreaseLiquidity.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,14 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers {
mint(config, liquidityAlice, alice, ZERO_BYTES);
vm.stopPrank();

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenIdAlice));
uint128 oldLiquidity = StateLibrary.getPositionLiquidity(manager, config.poolKey.toId(), positionId);
uint256 oldLiquidity = _getPositionLiquidity(tokenIdAlice, config);

// bob can increase liquidity for alice even though he is not the owner / not approved
vm.startPrank(bob);
increaseLiquidity(tokenIdAlice, config, 100e18, ZERO_BYTES);
vm.stopPrank();

uint128 newLiquidity = StateLibrary.getPositionLiquidity(manager, config.poolKey.toId(), positionId);
uint128 newLiquidity = _getPositionLiquidity(tokenIdAlice, config);

// assert liqudity increased by the correct amount
assertEq(newLiquidity, oldLiquidity + uint128(100e18));
Expand Down Expand Up @@ -415,9 +413,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers {
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);
uint256 liquidity = _getPositionLiquidity(tokenIdAlice, config);
assertEq(liquidity, liquidityAlice);

// alice increases with the balance in the position manager
Expand Down Expand Up @@ -448,7 +444,7 @@ contract IncreaseLiquidityTest is Test, PosmTestSetup, Fuzzers {
uint256 amount0 = uint128(-delta.amount0());
uint256 amount1 = uint128(-delta.amount1());

(liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
liquidity = _getPositionLiquidity(tokenIdAlice, config);
assertEq(liquidity, 2 * liquidityAlice);

// The balances were swept back to this address.
Expand Down
35 changes: 9 additions & 26 deletions test/position-managers/NativeToken.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {Constants} from "@uniswap/v4-core/test/utils/Constants.sol";
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol";
import {Position} from "@uniswap/v4-core/src/libraries/Position.sol";

import {IERC20} from "forge-std/interfaces/IERC20.sol";
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
Expand All @@ -39,7 +37,6 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
using PositionConfigLibrary for PositionConfig;
using Planner for Plan;
using PoolIdLibrary for PoolKey;
using StateLibrary for IPoolManager;
using SafeCast for *;

PoolId poolId;
Expand Down Expand Up @@ -86,9 +83,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
lpm.modifyLiquidities{value: amount0 + 1}(calls, _deadline);
BalanceDelta delta = getLastDelta();

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);

assertEq(liquidity, uint256(params.liquidityDelta));
assertEq(balance0Before - currency0.balanceOfSelf(), uint256(int256(-delta.amount0())), "incorrect amount0");
Expand Down Expand Up @@ -130,9 +125,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
lpm.modifyLiquidities{value: amount0 * 2 + 1}(calls, _deadline);
BalanceDelta delta = getLastDelta();

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, uint256(params.liquidityDelta));

// only paid the delta amount, with excess tokens returned to caller
Expand All @@ -156,9 +149,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
uint256 tokenId = lpm.nextTokenId();
mintWithNative(SQRT_PRICE_1_1, config, liquidityToAdd, address(this), ZERO_BYTES);

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, uint256(params.liquidityDelta));

// burn liquidity
Expand All @@ -173,7 +164,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
// No decrease/modifyLiq call will actually happen on the call to burn so the deltas array will be the same length.
assertEq(numDeltas, hook.numberDeltasReturned());

(liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, 0);

// TODO: slightly off by 1 bip (0.0001%)
Expand Down Expand Up @@ -209,9 +200,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
uint256 tokenId = lpm.nextTokenId();
mintWithNative(SQRT_PRICE_1_1, config, liquidityToAdd, address(this), ZERO_BYTES);

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, uint256(params.liquidityDelta));

// burn liquidity
Expand All @@ -221,7 +210,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
burn(tokenId, config, ZERO_BYTES);
BalanceDelta deltaBurn = getLastDelta();

(liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, 0);

// TODO: slightly off by 1 bip (0.0001%)
Expand Down Expand Up @@ -272,9 +261,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
BalanceDelta delta = getLastDelta();

// verify position liquidity increased
bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, liquidityToAdd + liquidityToAdd); // liquidity was doubled

// verify native token balances changed as expected
Expand Down Expand Up @@ -321,9 +308,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
BalanceDelta delta = getLastDelta();

// verify position liquidity increased
bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, liquidityToAdd + liquidityToAdd); // liquidity was doubled

// verify native token balances changed as expected, with overpaid tokens returned
Expand Down Expand Up @@ -360,9 +345,7 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
decreaseLiquidity(tokenId, config, decreaseLiquidityDelta, ZERO_BYTES);
BalanceDelta delta = getLastDelta();

bytes32 positionId =
Position.calculatePositionKey(address(lpm), config.tickLower, config.tickUpper, bytes32(tokenId));
(uint256 liquidity,,) = manager.getPositionInfo(config.poolKey.toId(), positionId);
uint256 liquidity = _getPositionLiquidity(tokenId, config);
assertEq(liquidity, uint256(params.liquidityDelta) - decreaseLiquidityDelta);

// verify native token balances changed as expected
Expand Down
Loading

0 comments on commit 5d815cd

Please sign in to comment.