feat(libraries): add single-step swap math
This commit is contained in:
1 parent
7a1aff4521
commit
b9dcfdcf4e
1 file changed
+74
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.36;
|
||||
|
||||
import {FullMath} from "./FullMath.sol";
|
||||
import {SqrtPriceMath} from "./SqrtPriceMath.sol";
|
||||
|
||||
/// @title One swap step within a single tick range, fee inclusive.
|
||||
library SwapMath {
|
||||
function computeSwapStep(
|
||||
uint160 sqrtRatioCurrentX96,
|
||||
uint160 sqrtRatioTargetX96,
|
||||
uint128 liquidity,
|
||||
int256 amountRemaining,
|
||||
uint24 feePips
|
||||
) internal pure returns (uint160 sqrtRatioNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) {
|
||||
unchecked {
|
||||
bool zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96;
|
||||
bool exactIn = amountRemaining >= 0;
|
||||
|
||||
if (exactIn) {
|
||||
uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(amountRemaining), 1e6 - feePips, 1e6);
|
||||
amountIn = zeroForOne
|
||||
? SqrtPriceMath.getAmount0Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, true)
|
||||
: SqrtPriceMath.getAmount1Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, true);
|
||||
if (amountRemainingLessFee >= amountIn) {
|
||||
sqrtRatioNextX96 = sqrtRatioTargetX96;
|
||||
} else {
|
||||
sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput(
|
||||
sqrtRatioCurrentX96, liquidity, amountRemainingLessFee, zeroForOne
|
||||
);
|
||||
}
|
||||
} else {
|
||||
amountOut = zeroForOne
|
||||
? SqrtPriceMath.getAmount1Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)
|
||||
: SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false);
|
||||
if (uint256(-amountRemaining) >= amountOut) {
|
||||
sqrtRatioNextX96 = sqrtRatioTargetX96;
|
||||
} else {
|
||||
sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput(
|
||||
sqrtRatioCurrentX96, liquidity, uint256(-amountRemaining), zeroForOne
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool reachedTarget = sqrtRatioTargetX96 == sqrtRatioNextX96;
|
||||
|
||||
if (zeroForOne) {
|
||||
amountIn = reachedTarget && exactIn
|
||||
? amountIn
|
||||
: SqrtPriceMath.getAmount0Delta(sqrtRatioNextX96, sqrtRatioCurrentX96, liquidity, true);
|
||||
amountOut = reachedTarget && !exactIn
|
||||
? amountOut
|
||||
: SqrtPriceMath.getAmount1Delta(sqrtRatioNextX96, sqrtRatioCurrentX96, liquidity, false);
|
||||
} else {
|
||||
amountIn = reachedTarget && exactIn
|
||||
? amountIn
|
||||
: SqrtPriceMath.getAmount1Delta(sqrtRatioCurrentX96, sqrtRatioNextX96, liquidity, true);
|
||||
amountOut = reachedTarget && !exactIn
|
||||
? amountOut
|
||||
: SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioNextX96, liquidity, false);
|
||||
}
|
||||
|
||||
if (!exactIn && amountOut > uint256(-amountRemaining)) {
|
||||
amountOut = uint256(-amountRemaining);
|
||||
}
|
||||
|
||||
if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) {
|
||||
feeAmount = uint256(amountRemaining) - amountIn;
|
||||
} else {
|
||||
feeAmount = FullMath.mulDivRoundingUp(amountIn, feePips, 1e6 - feePips);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user