-
Notifications
You must be signed in to change notification settings - Fork 504
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0c162a0
commit 9700e0e
Showing
4 changed files
with
236 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.20; | ||
|
||
import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; | ||
import {FixedPoint96} from "@uniswap/v4-core/src/libraries/FixedPoint96.sol"; | ||
|
||
/// @notice Provides functions for computing liquidity amounts from token amounts and prices | ||
library LiquidityAmounts { | ||
/// @notice Downcasts uint256 to uint128 | ||
/// @param x The uint258 to be downcasted | ||
/// @return y The passed value, downcasted to uint128 | ||
function toUint128(uint256 x) private pure returns (uint128 y) { | ||
require((y = uint128(x)) == x, "liquidity overflow"); | ||
} | ||
|
||
/// @notice Computes the amount of liquidity received for a given amount of token0 and price range | ||
/// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower)) | ||
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary | ||
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary | ||
/// @param amount0 The amount0 being sent in | ||
/// @return liquidity The amount of returned liquidity | ||
function getLiquidityForAmount0(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount0) | ||
internal | ||
pure | ||
returns (uint128 liquidity) | ||
{ | ||
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); | ||
uint256 intermediate = FullMath.mulDiv(sqrtPriceAX96, sqrtPriceBX96, FixedPoint96.Q96); | ||
return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtPriceBX96 - sqrtPriceAX96)); | ||
} | ||
|
||
/// @notice Computes the amount of liquidity received for a given amount of token1 and price range | ||
/// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)). | ||
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary | ||
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary | ||
/// @param amount1 The amount1 being sent in | ||
/// @return liquidity The amount of returned liquidity | ||
function getLiquidityForAmount1(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount1) | ||
internal | ||
pure | ||
returns (uint128 liquidity) | ||
{ | ||
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); | ||
return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtPriceBX96 - sqrtPriceAX96)); | ||
} | ||
|
||
/// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current | ||
/// pool prices and the prices at the tick boundaries | ||
/// @param sqrtPriceX96 A sqrt price representing the current pool prices | ||
/// @param sqrtPriceAX96 A sqrt price representing the first tick boundary | ||
/// @param sqrtPriceBX96 A sqrt price representing the second tick boundary | ||
/// @param amount0 The amount of token0 being sent in | ||
/// @param amount1 The amount of token1 being sent in | ||
/// @return liquidity The maximum amount of liquidity received | ||
function getLiquidityForAmounts( | ||
uint160 sqrtPriceX96, | ||
uint160 sqrtPriceAX96, | ||
uint160 sqrtPriceBX96, | ||
uint256 amount0, | ||
uint256 amount1 | ||
) internal pure returns (uint128 liquidity) { | ||
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); | ||
|
||
if (sqrtPriceX96 <= sqrtPriceAX96) { | ||
liquidity = getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0); | ||
} else if (sqrtPriceX96 < sqrtPriceBX96) { | ||
uint128 liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0); | ||
uint128 liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1); | ||
|
||
liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1; | ||
} else { | ||
liquidity = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1); | ||
} | ||
} | ||
} |