Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

add from amount support #384

Merged
merged 16 commits into from
Nov 22, 2024
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_burn_empty.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
50446
50507
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 @@
50446
50507
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125584
125644
Original file line number Diff line number Diff line change
@@ -1 +1 @@
125031
125092
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132446
132507
Original file line number Diff line number Diff line change
@@ -1 +1 @@
131893
131954
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_collect_native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146294
146317
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_collect_sameRange.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
154872
154895
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_collect_withClose.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
154872
154895
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_collect_withTakePair.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
154193
154216
Original file line number Diff line number Diff line change
@@ -1 +1 @@
111980
111999
Original file line number Diff line number Diff line change
@@ -1 +1 @@
119753
119776
Original file line number Diff line number Diff line change
@@ -1 +1 @@
119074
119097
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_decrease_burnEmpty.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
135243
135322
Original file line number Diff line number Diff line change
@@ -1 +1 @@
128380
128460
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132440
132463
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_decrease_take_take.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120329
120352
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_mint_native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
364745
364768
Original file line number Diff line number Diff line change
@@ -1 +1 @@
373268
373291
Original file line number Diff line number Diff line change
@@ -1 +1 @@
372491
372514
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_mint_onSameTickLower.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
317617
317640
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_mint_onSameTickUpper.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
318287
318310
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_mint_sameRange.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
243856
243879
Original file line number Diff line number Diff line change
@@ -1 +1 @@
419060
419083
Original file line number Diff line number Diff line change
@@ -1 +1 @@
323648
323671
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_mint_withClose.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
420170
420193
2 changes: 1 addition & 1 deletion .forge-snapshots/PositionManager_mint_withSettlePair.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
419228
419251
Original file line number Diff line number Diff line change
@@ -1 +1 @@
455975
455998
87 changes: 86 additions & 1 deletion src/PositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ 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 {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol";
import {IPositionDescriptor} from "./interfaces/IPositionDescriptor.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";

import {IPositionDescriptor} from "./interfaces/IPositionDescriptor.sol";
import {ERC721Permit_v4} from "./base/ERC721Permit_v4.sol";
import {ReentrancyLock} from "./base/ReentrancyLock.sol";
import {IPositionManager} from "./interfaces/IPositionManager.sol";
Expand All @@ -26,6 +27,7 @@ import {CalldataDecoder} from "./libraries/CalldataDecoder.sol";
import {Permit2Forwarder} from "./base/Permit2Forwarder.sol";
import {SlippageCheck} from "./libraries/SlippageCheck.sol";
import {PositionInfo, PositionInfoLibrary} from "./libraries/PositionInfoLibrary.sol";
import {LiquidityAmounts} from "./libraries/LiquidityAmounts.sol";
hensha256 marked this conversation as resolved.
Show resolved Hide resolved

// 444444444
// 444444444444 444444
Expand Down Expand Up @@ -188,6 +190,18 @@ contract PositionManager is
params.decodeModifyLiquidityParams();
_increase(tokenId, liquidity, amount0Max, amount1Max, hookData);
return;
} else if (action == Actions.INCREASE_LIQUIDITY_FROM_AMOUNTS) {
(
uint256 tokenId,
uint128 amount0,
uint128 amount1,
uint128 amount0Max,
uint128 amount1Max,
bytes calldata hookData
) = params.decodeIncreaseLiquidityFromAmountsParams();
// note the amounts are mapped inside _increaseFromAmounts
_increaseFromAmounts(tokenId, amount0, amount1, amount0Max, amount1Max, hookData);
return;
} else if (action == Actions.DECREASE_LIQUIDITY) {
(uint256 tokenId, uint256 liquidity, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) =
params.decodeModifyLiquidityParams();
Expand All @@ -206,6 +220,22 @@ contract PositionManager is
) = params.decodeMintParams();
_mint(poolKey, tickLower, tickUpper, liquidity, amount0Max, amount1Max, _mapRecipient(owner), hookData);
return;
} else if (action == Actions.MINT_POSITION_FROM_AMOUNTS) {
(
PoolKey calldata poolKey,
int24 tickLower,
int24 tickUpper,
uint128 amount0,
hensha256 marked this conversation as resolved.
Show resolved Hide resolved
uint128 amount1,
uint128 amount0Max,
uint128 amount1Max,
address owner,
bytes calldata hookData
) = params.decodeMintFromAmountsParams();
_mintFromAmounts(
poolKey, tickLower, tickUpper, amount0, amount1, amount0Max, amount1Max, owner, hookData
);
return;
} else if (action == Actions.BURN_POSITION) {
// Will automatically decrease liquidity to 0 if the position is not already empty.
(uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) =
Expand Down Expand Up @@ -264,6 +294,37 @@ contract PositionManager is
(liquidityDelta - feesAccrued).validateMaxIn(amount0Max, amount1Max);
}

/// @dev The amounts can be mapped to the open delta in the pool manager
function _increaseFromAmounts(
uint256 tokenId,
uint128 amount0,
uint128 amount1,
uint128 amount0Max,
uint128 amount1Max,
bytes calldata hookData
) internal onlyIfApproved(msgSender(), tokenId) {
(PoolKey memory poolKey, PositionInfo info) = getPoolAndPositionInfo(tokenId);

amount0 = uint128(_mapTakeAmount(uint256(amount0), poolKey.currency0));
amount1 = uint128(_mapTakeAmount(uint256(amount1), poolKey.currency1));

(uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolKey.toId());

uint256 liquidity = LiquidityAmounts.getLiquidityForAmounts(
sqrtPriceX96,
TickMath.getSqrtPriceAtTick(info.tickLower()),
TickMath.getSqrtPriceAtTick(info.tickUpper()),
amount0,
amount1
);

// Note: The tokenId is used as the salt for this position, so every minted position has unique storage in the pool manager.
(BalanceDelta liquidityDelta, BalanceDelta feesAccrued) =
_modifyLiquidity(info, poolKey, liquidity.toInt256(), bytes32(tokenId), hookData);
// Slippage checks should be done on the principal liquidityDelta which is the liquidityDelta - feesAccrued
(liquidityDelta - feesAccrued).validateMaxIn(amount0Max, amount1Max);
}

/// @dev Calling decrease with 0 liquidity will credit the caller with any underlying fees of the position
function _decrease(
uint256 tokenId,
Expand Down Expand Up @@ -316,6 +377,30 @@ contract PositionManager is
liquidityDelta.validateMaxIn(amount0Max, amount1Max);
}

function _mintFromAmounts(
PoolKey calldata poolKey,
int24 tickLower,
int24 tickUpper,
uint128 amount0,
uint128 amount1,
uint128 amount0Max,
uint128 amount1Max,
address owner,
bytes calldata hookData
) internal {
(uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolKey.toId());

uint256 liquidity = LiquidityAmounts.getLiquidityForAmounts(
sqrtPriceX96,
TickMath.getSqrtPriceAtTick(tickLower),
TickMath.getSqrtPriceAtTick(tickUpper),
amount0,
amount1
);

_mint(poolKey, tickLower, tickUpper, uint256(liquidity), amount0Max, amount1Max, owner, hookData);
hensha256 marked this conversation as resolved.
Show resolved Hide resolved
}

/// @dev this is overloaded with ERC721Permit_v4._burn
function _burn(uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData)
internal
Expand Down
39 changes: 21 additions & 18 deletions src/libraries/Actions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,34 @@ library Actions {
uint256 constant DECREASE_LIQUIDITY = 0x01;
uint256 constant MINT_POSITION = 0x02;
uint256 constant BURN_POSITION = 0x03;
uint256 constant INCREASE_LIQUIDITY_FROM_AMOUNTS = 0x04;
uint256 constant MINT_POSITION_FROM_AMOUNTS = 0x05;

// 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;
uint256 constant SWAP_EXACT_IN_SINGLE = 0x06;
hensha256 marked this conversation as resolved.
Show resolved Hide resolved
uint256 constant SWAP_EXACT_IN = 0x07;
uint256 constant SWAP_EXACT_OUT_SINGLE = 0x08;
uint256 constant SWAP_EXACT_OUT = 0x09;
// donate
uint256 constant DONATE = 0x08;
uint256 constant DONATE = 0x10;

// closing deltas on the pool manager
// settling
uint256 constant SETTLE = 0x09;
uint256 constant SETTLE_ALL = 0x10;
uint256 constant SETTLE_PAIR = 0x11;
uint256 constant SETTLE = 0x11;
uint256 constant SETTLE_ALL = 0x12;
uint256 constant SETTLE_PAIR = 0x13;
// taking
uint256 constant TAKE = 0x12;
uint256 constant TAKE_ALL = 0x13;
uint256 constant TAKE_PORTION = 0x14;
uint256 constant TAKE_PAIR = 0x15;
uint256 constant TAKE = 0x14;
uint256 constant TAKE_ALL = 0x15;
uint256 constant TAKE_PORTION = 0x16;
uint256 constant TAKE_PAIR = 0x17;

uint256 constant SETTLE_TAKE_PAIR = 0x16;
uint256 constant CLOSE_CURRENCY = 0x17;
uint256 constant CLEAR_OR_TAKE = 0x18;
uint256 constant SWEEP = 0x19;
uint256 constant SETTLE_TAKE_PAIR = 0x18;
uint256 constant CLOSE_CURRENCY = 0x19;
uint256 constant CLEAR_OR_TAKE = 0x20;
snreynolds marked this conversation as resolved.
Show resolved Hide resolved
uint256 constant SWEEP = 0x21;

// minting/burning 6909s to close deltas
uint256 constant MINT_6909 = 0x20;
uint256 constant BURN_6909 = 0x21;
uint256 constant MINT_6909 = 0x22;
uint256 constant BURN_6909 = 0x23;
}
54 changes: 54 additions & 0 deletions src/libraries/CalldataDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,30 @@ library CalldataDecoder {
hookData = params.toBytes(4);
}

/// @dev equivalent to: abi.decode(params, (uint256, uint256, uint256, uint128, uint128, bytes)) in calldata
function decodeIncreaseLiquidityFromAmountsParams(bytes calldata params)
internal
pure
returns (
uint256 tokenId,
uint128 amount0,
uint128 amount1,
uint128 amount0Max,
uint128 amount1Max,
bytes calldata hookData
)
{
assembly ("memory-safe") {
tokenId := calldataload(params.offset)
amount0 := calldataload(add(params.offset, 0x20))
amount1 := calldataload(add(params.offset, 0x40))
amount0Max := calldataload(add(params.offset, 0x60))
amount1Max := calldataload(add(params.offset, 0x80))
}

hookData = params.toBytes(5);
}

/// @dev equivalent to: abi.decode(params, (PoolKey, int24, int24, uint256, uint128, uint128, address, bytes)) in calldata
function decodeMintParams(bytes calldata params)
internal
Expand Down Expand Up @@ -113,6 +137,36 @@ library CalldataDecoder {
hookData = params.toBytes(11);
}

/// @dev equivalent to: abi.decode(params, (PoolKey, int24, int24, uint128, uint128, uint128, uint128, address, bytes)) in calldata
function decodeMintFromAmountsParams(bytes calldata params)
internal
pure
returns (
PoolKey calldata poolKey,
int24 tickLower,
int24 tickUpper,
uint128 amount0,
uint128 amount1,
uint128 amount0Max,
uint128 amount1Max,
address owner,
bytes calldata hookData
)
{
assembly ("memory-safe") {
poolKey := params.offset
tickLower := calldataload(add(params.offset, 0xa0))
tickUpper := calldataload(add(params.offset, 0xc0))
amount0 := calldataload(add(params.offset, 0xe0))
amount1 := calldataload(add(params.offset, 0x100))
amount0Max := calldataload(add(params.offset, 0x120))
amount1Max := calldataload(add(params.offset, 0x140))
owner := calldataload(add(params.offset, 0x160))
}

hookData = params.toBytes(12);
}

/// @dev equivalent to: abi.decode(params, (uint256, uint128, uint128, bytes)) in calldata
function decodeBurnParams(bytes calldata params)
internal
Expand Down
Loading
Loading