Skip to content

Commit

Permalink
amountSpecified matches deltas (#491)
Browse files Browse the repository at this point in the history
Co-authored-by: hensha256 <[email protected]>
  • Loading branch information
ewilz and hensha256 authored Mar 6, 2024
1 parent 0043fa4 commit 1a76db2
Show file tree
Hide file tree
Showing 35 changed files with 128 additions and 136 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactInCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2203
1947
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactInPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3028
3238
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactOutCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1963
2208
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactOutPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3028
3238
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactInCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2193
1937
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactInPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3181
2826
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactOutCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1953
2198
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactOutPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3181
2826
Original file line number Diff line number Diff line change
@@ -1 +1 @@
185335
184850
2 changes: 1 addition & 1 deletion .forge-snapshots/cached dynamic fee, no hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
139362
138877
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23388
23323
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap with native.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
187932
187447
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
196472
195987
2 changes: 1 addition & 1 deletion .forge-snapshots/simpleSwapEOAInitiated.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
167083
166598
2 changes: 1 addition & 1 deletion .forge-snapshots/simpleSwapNativeEOAInitiated.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
165611
165126
Original file line number Diff line number Diff line change
@@ -1 +1 @@
118595
118106
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
106062
105573
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
126218
125700
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn native 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
122171
121653
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint native output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
190494
190005
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
207299
206814
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
184436
183951
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
106040
105551
2 changes: 1 addition & 1 deletion .forge-snapshots/update dynamic fee in before swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
191140
190655
2 changes: 1 addition & 1 deletion src/PoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ contract PoolManager is IPoolManager, Fees, NoDelegateCall, ERC6909Claims {
}

emit Swap(
id, msg.sender, -delta.amount0(), -delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
id, msg.sender, delta.amount0(), delta.amount1(), state.sqrtPriceX96, state.liquidity, state.tick, swapFee
);

key.hooks.afterSwap(key, params, delta, hookData);
Expand Down
18 changes: 9 additions & 9 deletions src/libraries/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ library Pool {
protocolFee: params.zeroForOne ? uint8(slot0Start.protocolFee % 256) : uint8(slot0Start.protocolFee >> 8)
});

bool exactInput = params.amountSpecified > 0;
bool exactInput = params.amountSpecified < 0;

state = SwapState({
amountSpecifiedRemaining: params.amountSpecified,
Expand Down Expand Up @@ -371,14 +371,14 @@ library Pool {
if (exactInput) {
// safe because we test that amountSpecified > amountIn + feeAmount in SwapMath
unchecked {
state.amountSpecifiedRemaining -= (step.amountIn + step.feeAmount).toInt256();
state.amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256();
}
state.amountCalculated = state.amountCalculated - step.amountOut.toInt256();
state.amountCalculated = state.amountCalculated + step.amountOut.toInt256();
} else {
unchecked {
state.amountSpecifiedRemaining += step.amountOut.toInt256();
state.amountSpecifiedRemaining -= step.amountOut.toInt256();
}
state.amountCalculated = state.amountCalculated + (step.amountIn + step.feeAmount).toInt256();
state.amountCalculated = state.amountCalculated - (step.amountIn + step.feeAmount).toInt256();
}

// if the protocol fee is on, calculate how much is owed, decrement feeAmount, and increment protocolFee
Expand Down Expand Up @@ -445,13 +445,13 @@ library Pool {
unchecked {
if (params.zeroForOne == exactInput) {
result = toBalanceDelta(
(params.amountSpecified - state.amountSpecifiedRemaining).toInt128().flipSign(),
state.amountCalculated.toInt128().flipSign()
(params.amountSpecified - state.amountSpecifiedRemaining).toInt128(),
state.amountCalculated.toInt128()
);
} else {
result = toBalanceDelta(
state.amountCalculated.toInt128().flipSign(),
(params.amountSpecified - state.amountSpecifiedRemaining).toInt128().flipSign()
state.amountCalculated.toInt128(),
(params.amountSpecified - state.amountSpecifiedRemaining).toInt128()
);
}
}
Expand Down
8 changes: 0 additions & 8 deletions src/libraries/SafeCast.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,4 @@ library SafeCast {
if (y > uint128(type(int128).max)) revert SafeCastOverflow();
z = int128(int256(y));
}

/// @notice Flip the sign of an int128, revert on overflow
/// @param y The int128 to flip the sign of
/// @return The flipped integer, still an int128
function flipSign(int128 y) internal pure returns (int128) {
// this is not unchecked, so it will revert if y==type(int128).min
return -y;
}
}
14 changes: 7 additions & 7 deletions src/libraries/SwapMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ library SwapMath {
) internal pure returns (uint160 sqrtRatioNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) {
unchecked {
bool zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96;
bool exactIn = amountRemaining >= 0;
bool exactIn = amountRemaining < 0;

if (exactIn) {
uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(amountRemaining), 1e6 - feePips, 1e6);
uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(-amountRemaining), 1e6 - feePips, 1e6);
amountIn = zeroForOne
? SqrtPriceMath.getAmount0Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, true)
: SqrtPriceMath.getAmount1Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, true);
Expand All @@ -45,11 +45,11 @@ library SwapMath {
amountOut = zeroForOne
? SqrtPriceMath.getAmount1Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)
: SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false);
if (uint256(-amountRemaining) >= amountOut) {
if (uint256(amountRemaining) >= amountOut) {
sqrtRatioNextX96 = sqrtRatioTargetX96;
} else {
sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput(
sqrtRatioCurrentX96, liquidity, uint256(-amountRemaining), zeroForOne
sqrtRatioCurrentX96, liquidity, uint256(amountRemaining), zeroForOne
);
}
}
Expand All @@ -74,13 +74,13 @@ library SwapMath {
}

// cap the output amount to not exceed the remaining output amount
if (!exactIn && amountOut > uint256(-amountRemaining)) {
amountOut = uint256(-amountRemaining);
if (!exactIn && amountOut > uint256(amountRemaining)) {
amountOut = uint256(amountRemaining);
}

if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) {
// we didn't reach the target, so take the remainder of the maximum input as fee
feeAmount = uint256(amountRemaining) - amountIn;
feeAmount = uint256(-amountRemaining) - amountIn;
} else {
feeAmount = FullMath.mulDivRoundingUp(amountIn, feePips, 1e6 - feePips);
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/PoolNestedActionsTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ contract NestedActionExecutor is Test, PoolTestBase {
IPoolManager.ModifyLiquidityParams({tickLower: -120, tickUpper: 120, liquidityDelta: -1e18});

IPoolManager.SwapParams internal SWAP_PARAMS =
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: Constants.SQRT_RATIO_1_2});

uint256 internal DONATE_AMOUNT0 = 12345e6;
uint256 internal DONATE_AMOUNT1 = 98765e4;
Expand Down Expand Up @@ -124,7 +124,7 @@ contract NestedActionExecutor is Test, PoolTestBase {

assertEq(deltaLockerBefore0, deltaLockerAfter0, "Locker delta 0");
assertEq(deltaLockerBefore1, deltaLockerAfter1, "Locker delta 1");
assertEq(deltaThisBefore0 - SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
assertEq(deltaThisBefore0 + SWAP_PARAMS.amountSpecified, deltaThisAfter0, "Executor delta 0");
assertEq(deltaThisBefore1 + 98, deltaThisAfter1, "Executor delta 1");
assertEq(delta.amount0(), deltaThisAfter0, "Swap delta 0");
assertEq(delta.amount1(), deltaThisAfter1, "Swap delta 1");
Expand Down
12 changes: 6 additions & 6 deletions src/test/PoolSwapTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,24 @@ contract PoolSwapTest is Test, PoolTestBase {
assertEq(reserveBefore1, reserveAfter1);

if (data.params.zeroForOne) {
if (data.params.amountSpecified > 0) {
if (data.params.amountSpecified < 0) {
// exact input, 0 for 1
assertEq(-deltaAfter0, data.params.amountSpecified);
assertEq(deltaAfter0, data.params.amountSpecified);
assertGt(deltaAfter1, 0);
} else {
// exact output, 0 for 1
assertLt(deltaAfter0, 0);
assertEq(-deltaAfter1, data.params.amountSpecified);
assertEq(deltaAfter1, data.params.amountSpecified);
}
} else {
if (data.params.amountSpecified > 0) {
if (data.params.amountSpecified < 0) {
// exact input, 1 for 0
assertEq(-deltaAfter1, data.params.amountSpecified);
assertEq(deltaAfter1, data.params.amountSpecified);
assertGt(deltaAfter0, 0);
} else {
// exact output, 1 for 0
assertLt(deltaAfter1, 0);
assertEq(-deltaAfter0, data.params.amountSpecified);
assertEq(deltaAfter0, data.params.amountSpecified);
}
}

Expand Down
16 changes: 8 additions & 8 deletions test/DynamicFees.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
manager.updateDynamicSwapFee(key);

IPoolManager.SwapParams memory params =
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});

vm.expectEmit(true, true, true, true, address(manager));
emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 123);
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);

snapStart("swap with dynamic fee");
swapRouter.swap(key, params, testSettings, ZERO_BYTES);
Expand All @@ -120,12 +120,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
manager.updateDynamicSwapFee(key);

IPoolManager.SwapParams memory params =
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});

vm.expectEmit(true, true, true, true, address(manager));
emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 456);
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 456);
bytes memory data = abi.encode(true, uint24(456));

snapStart("update dynamic fee in before swap");
Expand All @@ -138,12 +138,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
manager.updateDynamicSwapFee(key);

IPoolManager.SwapParams memory params =
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});

vm.expectEmit(true, true, true, true, address(manager));
emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 123);
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);
bytes memory data = abi.encode(false, uint24(0));

snapStart("before swap hook, already cached dynamic fee");
Expand All @@ -166,12 +166,12 @@ contract TestDynamicFees is Test, Deployers, GasSnapshot {
manager.updateDynamicSwapFee(key);

IPoolManager.SwapParams memory params =
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: 100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
IPoolManager.SwapParams({zeroForOne: true, amountSpecified: -100, sqrtPriceLimitX96: SQRT_RATIO_1_2});
PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true, currencyAlreadySent: false});

vm.expectEmit(true, true, true, true, address(manager));
emit Swap(key.toId(), address(swapRouter), 100, -98, 79228162514264329749955861424, 1e18, -1, 123);
emit Swap(key.toId(), address(swapRouter), -100, 98, 79228162514264329749955861424, 1e18, -1, 123);

snapStart("cached dynamic fee, no hooks");
swapRouter.swap(key, params, testSettings, ZERO_BYTES);
Expand Down
Loading

0 comments on commit 1a76db2

Please sign in to comment.