Skip to content

Commit

Permalink
Take (#257)
Browse files Browse the repository at this point in the history
* add take

* merge conf

* noooo console

* pr comments
  • Loading branch information
snreynolds authored Aug 3, 2024
1 parent 1f28ac2 commit 2f15bb2
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 3 deletions.
1 change: 1 addition & 0 deletions .forge-snapshots/PositionManager_decrease_take_take.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
116877

This file was deleted.

1 change: 0 additions & 1 deletion .forge-snapshots/PositionManager_mint.snap

This file was deleted.

1 change: 0 additions & 1 deletion .forge-snapshots/PositionManager_mint_nativeWithSweep.snap

This file was deleted.

3 changes: 3 additions & 0 deletions src/PositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ contract PositionManager is
} else if (action == Actions.SWEEP) {
(Currency currency, address to) = params.decodeCurrencyAndAddress();
_sweep(currency, _mapRecipient(to));
} else if (action == Actions.TAKE) {
(Currency currency, address recipient, uint256 amount) = params.decodeCurrencyAddressAndUint256();
_take(currency, _mapRecipient(recipient), _mapTakeAmount(amount, currency));
} else {
revert UnsupportedAction(action);
}
Expand Down
8 changes: 8 additions & 0 deletions src/base/DeltaResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ abstract contract DeltaResolver is ImmutableState {
return amount;
}

/// @notice Calculates the amount for a take action
function _mapTakeAmount(uint256 amount, Currency currency) internal view returns (uint256) {
if (amount == Constants.OPEN_DELTA) {
return _getFullCredit(currency).toUint128();
}
return amount;
}

/// @notice Calculates the amount for a swap action
function _mapInputAmount(uint128 amount, Currency currency) internal view returns (uint128) {
if (amount == Constants.CONTRACT_BALANCE) {
Expand Down
12 changes: 12 additions & 0 deletions test/libraries/CalldataDecoder.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,18 @@ contract CalldataDecoderTest is Test {
assertEq(_address, __address);
}

function test_fuzz_decodeCurrencyAddressAndUint256(Currency _currency, address _addr, uint256 _amount)
public
view
{
bytes memory params = abi.encode(_currency, _addr, _amount);
(Currency currency, address addr, uint256 amount) = decoder.decodeCurrencyAddressAndUint256(params);

assertEq(Currency.unwrap(currency), Currency.unwrap(_currency));
assertEq(addr, _addr);
assertEq(amount, _amount);
}

function test_fuzz_decodeCurrencyAndUint256(Currency _currency, uint256 _amount) public view {
bytes memory params = abi.encode(_currency, _amount);
(Currency currency, uint256 amount) = decoder.decodeCurrencyAndUint256(params);
Expand Down
8 changes: 8 additions & 0 deletions test/mocks/MockCalldataDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,12 @@ contract MockCalldataDecoder {
function decodeCurrencyAndUint256(bytes calldata params) external pure returns (Currency currency, uint256 _uint) {
return params.decodeCurrencyAndUint256();
}

function decodeCurrencyAddressAndUint256(bytes calldata params)
external
pure
returns (Currency currency, address addr, uint256 amount)
{
return params.decodeCurrencyAddressAndUint256();
}
}
16 changes: 16 additions & 0 deletions test/position-managers/PositionManager.gas.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -807,4 +807,20 @@ contract PosMGasTest is Test, PosmTestSetup, GasSnapshot {
lpm.modifyLiquidities(calls, _deadline);
snapLastCall("PositionManager_mint_settleWithBalance_sweep");
}

// Does not encode a take pair
function test_gas_decrease_take_take() public {
uint256 tokenId = lpm.nextTokenId();
mint(config, 1e18, Constants.MSG_SENDER, ZERO_BYTES);

Plan memory plan = Planner.init();
plan.add(
Actions.DECREASE_LIQUIDITY,
abi.encode(tokenId, config, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES)
);
bytes memory calls = plan.finalizeModifyLiquidityWithTake(config.poolKey, Constants.MSG_SENDER);

lpm.modifyLiquidities(calls, _deadline);
snapLastCall("PositionManager_decrease_take_take");
}
}
71 changes: 71 additions & 0 deletions test/position-managers/PositionManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -878,5 +878,76 @@ contract PositionManagerTest is Test, PosmTestSetup, LiquidityFuzzers {
assertEq(lpFee, fee);
}

// tests a decrease and take in both currencies
// does not use take pair, so its less optimal
function test_decrease_take() public {
PositionConfig memory config = PositionConfig({poolKey: key, tickLower: -120, tickUpper: 120});
uint256 tokenId = lpm.nextTokenId();
mint(config, 1e18, Constants.MSG_SENDER, ZERO_BYTES);

hook.clearDeltas();

uint256 balanceBefore0 = currency0.balanceOfSelf();
uint256 balanceBefore1 = currency1.balanceOfSelf();

Plan memory plan = Planner.init();
plan.add(
Actions.DECREASE_LIQUIDITY,
abi.encode(tokenId, config, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES)
);
bytes memory calls = plan.finalizeModifyLiquidityWithTake(config.poolKey, Constants.MSG_SENDER);

lpm.modifyLiquidities(calls, _deadline);
BalanceDelta delta = getLastDelta();

assertEq(currency0.balanceOfSelf(), balanceBefore0 + uint256(int256(delta.amount0())));
assertEq(currency1.balanceOfSelf(), balanceBefore1 + uint256(int256(delta.amount1())));
}

// decrease full range position
// mint new one sided position in currency1
// expect to TAKE currency0 and SETTLE currency1
function test_decrease_increaseCurrency1_take_settle() public {
PositionConfig memory config = PositionConfig({poolKey: key, tickLower: -120, tickUpper: 120});
uint256 tokenId = lpm.nextTokenId();
mint(config, 1e18, Constants.MSG_SENDER, ZERO_BYTES);

hook.clearDeltas();

uint256 balanceBefore0 = currency0.balanceOfSelf();
uint256 balanceBefore1 = currency1.balanceOfSelf();

uint256 tokenIdMint = lpm.nextTokenId();

// one-sided liq in currency1
PositionConfig memory configMint = PositionConfig({poolKey: key, tickLower: -120, tickUpper: 0});

Plan memory plan = Planner.init();
plan.add(
Actions.DECREASE_LIQUIDITY,
abi.encode(tokenId, config, 1e18, MIN_SLIPPAGE_DECREASE, MIN_SLIPPAGE_DECREASE, ZERO_BYTES)
);
plan.add(
Actions.MINT_POSITION,
abi.encode(configMint, 1e18, MAX_SLIPPAGE_INCREASE, MAX_SLIPPAGE_INCREASE, Constants.MSG_SENDER, ZERO_BYTES)
);
plan.add(Actions.TAKE, abi.encode(key.currency0, Constants.MSG_SENDER, Constants.OPEN_DELTA));
plan.add(Actions.SETTLE, abi.encode(key.currency1, Constants.OPEN_DELTA, true));
bytes memory calls = plan.finalizeModifyLiquidityWithTake(config.poolKey, Constants.MSG_SENDER);

lpm.modifyLiquidities(calls, _deadline);
BalanceDelta deltaDecrease = hook.deltas(0);
BalanceDelta deltaMint = hook.deltas(1);

assertEq(deltaMint.amount0(), 0); // there is no currency0 in the new position
assertEq(currency0.balanceOfSelf(), balanceBefore0 + uint256(int256(deltaDecrease.amount0())));
assertEq(
currency1.balanceOfSelf(), balanceBefore1 - uint256(-int256(deltaDecrease.amount1() + deltaMint.amount1()))
);
assertEq(lpm.ownerOf(tokenIdMint), address(this));
assertLt(currency1.balanceOfSelf(), balanceBefore1); // currency1 was owed
assertLt(uint256(int256(deltaDecrease.amount1())), uint256(int256(-deltaMint.amount1()))); // amount1 in the second position was greater than amount1 in the first position
}

function test_mint_slippageRevert() public {}
}
11 changes: 11 additions & 0 deletions test/shared/Planner.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {IPositionManager} from "../../src/interfaces/IPositionManager.sol";
import {Actions} from "../../src/libraries/Actions.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {Constants} from "../../src/libraries/Constants.sol";

struct Plan {
bytes actions;
Expand Down Expand Up @@ -37,6 +38,16 @@ library Planner {
return plan;
}

function finalizeModifyLiquidityWithTake(Plan memory plan, PoolKey memory poolKey, address takeRecipient)
internal
pure
returns (bytes memory)
{
plan.add(Actions.TAKE, abi.encode(poolKey.currency0, takeRecipient, Constants.OPEN_DELTA));
plan.add(Actions.TAKE, abi.encode(poolKey.currency1, takeRecipient, Constants.OPEN_DELTA));
return plan.encode();
}

function finalizeModifyLiquidityWithClose(Plan memory plan, PoolKey memory poolKey)
internal
pure
Expand Down

0 comments on commit 2f15bb2

Please sign in to comment.