Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1e9971d
Refactor and optimize `SwapMath`
shuhuiluo Jun 21, 2023
21e704f
Merge branch 'refs/heads/main' into optimize-swapmath
shuhuiluo Apr 4, 2024
4aea67d
Update `SwapMath` calculations and gas snapshots, change `test_entire…
shuhuiluo Apr 4, 2024
2e92f28
No assembly in `computeSwapStep`
shuhuiluo Apr 10, 2024
c1aacd2
Merge and update snapshots
shuhuiluo Apr 24, 2024
2b9e653
Avoid casting `feePips` multiple times
shuhuiluo Apr 24, 2024
4ec866d
Fix natspec
shuhuiluo Apr 24, 2024
1d3c707
Rename `sqrtRatio` to `sqrtPrice` in SwapMath and Pool libraries
shuhuiluo May 17, 2024
d1da419
Merge and update snapshots
shuhuiluo May 17, 2024
2a023c8
Refactor variable declaration in `SwapMath`
shuhuiluo May 17, 2024
2e350cf
Update test function to pure in SwapMath.t.sol
shuhuiluo May 17, 2024
842bda5
Optimize `getSqrtPriceTarget`
shuhuiluo May 17, 2024
57af2c2
Merge and update snapshots
shuhuiluo May 17, 2024
473efd3
Merge and update snapshots
shuhuiluo May 22, 2024
5a99fe0
Switch if else blocks for ease of review
shuhuiluo May 22, 2024
4178815
Refactor and reduce diffs
shuhuiluo May 22, 2024
bd41a45
Recompute `amountIn` when it's capped by `amountRemaining` instead of…
shuhuiluo May 22, 2024
cde8e3a
Remove `amountRemainingAbs`
shuhuiluo May 22, 2024
98f8e56
Merge and update snapshots
shuhuiluo May 23, 2024
eb15426
Remove .gas-snapshot
shuhuiluo May 23, 2024
02cc19f
Merge and update snapshots
shuhuiluo May 26, 2024
72be6c5
Address review comment
shuhuiluo May 26, 2024
1b9d60e
fmt
shuhuiluo May 26, 2024
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 @@
1947
1662
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactInPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2390
2152
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_oneForZero_exactOutCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1686
1413
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2831
2120
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactInCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2059
1753
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactInPartial.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2941
2671
2 changes: 1 addition & 1 deletion .forge-snapshots/SwapMath_zeroForOne_exactOutCapped.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1798
1504
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2458
1850
2 changes: 1 addition & 1 deletion .forge-snapshots/poolManager bytecode size.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19986
19871
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 @@
114924
114348
2 changes: 1 addition & 1 deletion .forge-snapshots/simple swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
130089
129513
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA fee on unspecified.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
179527
178951
Original file line number Diff line number Diff line change
@@ -1 +1 @@
110279
110009
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
121626
121356
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 @@
133455
132744
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 @@
122743
122135
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 @@
144531
144293
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 @@
161161
160585
Original file line number Diff line number Diff line change
@@ -1 +1 @@
217571
216725
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 @@
145362
144786
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
138626
138356
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with lp fee and protocol fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
176624
175722
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with return dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
152398
151822
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 @@
155040
154464
60 changes: 26 additions & 34 deletions src/libraries/SwapMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {SqrtPriceMath} from "./SqrtPriceMath.sol";
/// @title Computes the result of a swap within ticks
/// @notice Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick.
library SwapMath {
uint256 internal constant MAX_FEE_PIPS = 1e6;

/// @notice Computes the sqrt price target for the next swap step
/// @param zeroForOne The direction of the swap, true for currency0 to currency1, false for currency1 to currency0
/// @param sqrtPriceNextX96 The Q64.96 sqrt price for the next initialized tick
Expand Down Expand Up @@ -49,63 +51,53 @@ library SwapMath {
uint24 feePips
) internal pure returns (uint160 sqrtPriceNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) {
unchecked {
uint256 _feePips = feePips; // upcast once and cache
bool zeroForOne = sqrtPriceCurrentX96 >= sqrtPriceTargetX96;
bool exactIn = amountRemaining < 0;

if (exactIn) {
uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(-amountRemaining), 1e6 - feePips, 1e6);
uint256 amountRemainingLessFee =
FullMath.mulDiv(uint256(-amountRemaining), MAX_FEE_PIPS - _feePips, MAX_FEE_PIPS);
amountIn = zeroForOne
? SqrtPriceMath.getAmount0Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, true)
: SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, true);
if (amountRemainingLessFee >= amountIn) {
// `amountIn` is capped by the target price
sqrtPriceNextX96 = sqrtPriceTargetX96;
feeAmount = _feePips == MAX_FEE_PIPS
? amountIn
: FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_FEE_PIPS - _feePips);
Comment thread
hensha256 marked this conversation as resolved.
} else {
sqrtPriceNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput(
sqrtPriceCurrentX96, liquidity, amountRemainingLessFee, zeroForOne
);
amountIn = zeroForOne
? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true)
: SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true);
// we didn't reach the target, so take the remainder of the maximum input as fee
feeAmount = uint256(-amountRemaining) - amountIn;
}
amountOut = zeroForOne
? SqrtPriceMath.getAmount1Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, false)
: SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, false);
} else {
amountOut = zeroForOne
? SqrtPriceMath.getAmount1Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, false)
: SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, false);
if (uint256(amountRemaining) >= amountOut) {
// `amountOut` is capped by the target price
sqrtPriceNextX96 = sqrtPriceTargetX96;
} else {
sqrtPriceNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput(
sqrtPriceCurrentX96, liquidity, uint256(amountRemaining), zeroForOne
);
// cap the output amount to not exceed the remaining output amount
amountOut = uint256(amountRemaining);
sqrtPriceNextX96 =
SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtPriceCurrentX96, liquidity, amountOut, zeroForOne);
}
}

bool max = sqrtPriceTargetX96 == sqrtPriceNextX96;

// get the input/output amounts
if (zeroForOne) {
amountIn = max && exactIn
? amountIn
: SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true);
amountOut = max && !exactIn
? amountOut
: SqrtPriceMath.getAmount1Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, false);
} else {
amountIn = max && exactIn
? amountIn
amountIn = zeroForOne
? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true)
: SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true);
amountOut = max && !exactIn
? amountOut
: SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, false);
}

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

if (exactIn && sqrtPriceNextX96 != sqrtPriceTargetX96) {
// we didn't reach the target, so take the remainder of the maximum input as fee
feeAmount = uint256(-amountRemaining) - amountIn;
} else {
feeAmount = feePips == 1e6 ? amountIn : FullMath.mulDivRoundingUp(amountIn, feePips, 1e6 - feePips);
// `feePips` cannot be `MAX_FEE_PIPS` for exact out
feeAmount = FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_FEE_PIPS - _feePips);
}
}
}
Expand Down