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

POC: amountSpecified matches deltas #491

Merged
merged 2 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading