Qian V2 Contracts
Onchain token launch with permanently locked liquidity and DEX routing (Uniswap v3 + v4). No admin keys, no mint/blacklist. MIT licensed. Deployed addresses in README.
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Qian Exchange - https://qian.ag
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
/// @title LiquidityMath
|
||||
/// @notice Math library for calculating liquidity from amounts and tick ranges
|
||||
/// @dev Similar to Uniswap V3's LiquidityAmounts library
|
||||
library LiquidityMath {
|
||||
/// @notice Calculates the amount of liquidity for a given amount of token0
|
||||
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
|
||||
/// @param sqrtRatioBX96 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 sqrtRatioAX96,
|
||||
uint160 sqrtRatioBX96,
|
||||
uint256 amount0
|
||||
) internal pure returns (uint128 liquidity) {
|
||||
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
|
||||
uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);
|
||||
return uint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));
|
||||
}
|
||||
|
||||
/// @notice Calculates the amount of liquidity for a given amount of token1
|
||||
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
|
||||
/// @param sqrtRatioBX96 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 sqrtRatioAX96,
|
||||
uint160 sqrtRatioBX96,
|
||||
uint256 amount1
|
||||
) internal pure returns (uint128 liquidity) {
|
||||
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
|
||||
return uint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));
|
||||
}
|
||||
|
||||
/// @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 sqrtRatioX96 A sqrt price representing the current pool prices
|
||||
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
|
||||
/// @param sqrtRatioBX96 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 sqrtRatioX96,
|
||||
uint160 sqrtRatioAX96,
|
||||
uint160 sqrtRatioBX96,
|
||||
uint256 amount0,
|
||||
uint256 amount1
|
||||
) internal pure returns (uint128 liquidity) {
|
||||
if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
|
||||
|
||||
if (sqrtRatioX96 <= sqrtRatioAX96) {
|
||||
liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);
|
||||
} else if (sqrtRatioX96 < sqrtRatioBX96) {
|
||||
uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);
|
||||
uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);
|
||||
liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
|
||||
} else {
|
||||
liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Converts a tick to sqrt price
|
||||
/// @param tick The tick to convert
|
||||
/// @return sqrtPriceX96 The sqrt price
|
||||
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
|
||||
uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
|
||||
require(absTick <= uint256(int256(887272)), "T");
|
||||
|
||||
uint256 ratio = absTick & 0x1 != 0
|
||||
? 0xfffcb933bd6fad37aa2d162d1a594001
|
||||
: 0x100000000000000000000000000000000;
|
||||
if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
|
||||
if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
|
||||
if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
|
||||
if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
|
||||
if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
|
||||
if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
|
||||
if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
|
||||
if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
|
||||
if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
|
||||
if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
|
||||
if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
|
||||
if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
|
||||
if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
|
||||
if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
|
||||
if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
|
||||
if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
|
||||
if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
|
||||
if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
|
||||
if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
|
||||
|
||||
if (tick > 0) ratio = type(uint256).max / ratio;
|
||||
|
||||
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
|
||||
}
|
||||
}
|
||||
|
||||
/// @title FullMath
|
||||
/// @notice Math library for full precision multiplication and division
|
||||
library FullMath {
|
||||
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
|
||||
/// @param a The multiplicand
|
||||
/// @param b The multiplier
|
||||
/// @param denominator The divisor
|
||||
/// @return result The 256-bit result
|
||||
function mulDiv(
|
||||
uint256 a,
|
||||
uint256 b,
|
||||
uint256 denominator
|
||||
) internal pure returns (uint256 result) {
|
||||
unchecked {
|
||||
uint256 prod0;
|
||||
uint256 prod1;
|
||||
assembly {
|
||||
let mm := mulmod(a, b, not(0))
|
||||
prod0 := mul(a, b)
|
||||
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
|
||||
}
|
||||
|
||||
if (prod1 == 0) {
|
||||
require(denominator > 0);
|
||||
assembly {
|
||||
result := div(prod0, denominator)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
require(denominator > prod1);
|
||||
|
||||
uint256 remainder;
|
||||
assembly {
|
||||
remainder := mulmod(a, b, denominator)
|
||||
}
|
||||
assembly {
|
||||
prod1 := sub(prod1, gt(remainder, prod0))
|
||||
prod0 := sub(prod0, remainder)
|
||||
}
|
||||
|
||||
uint256 twos = (type(uint256).max - denominator + 1) & denominator;
|
||||
assembly {
|
||||
denominator := div(denominator, twos)
|
||||
}
|
||||
|
||||
assembly {
|
||||
prod0 := div(prod0, twos)
|
||||
}
|
||||
|
||||
assembly {
|
||||
twos := add(div(sub(0, twos), twos), 1)
|
||||
}
|
||||
prod0 |= prod1 * twos;
|
||||
|
||||
uint256 inv = (3 * denominator) ^ 2;
|
||||
inv *= 2 - denominator * inv;
|
||||
inv *= 2 - denominator * inv;
|
||||
inv *= 2 - denominator * inv;
|
||||
inv *= 2 - denominator * inv;
|
||||
inv *= 2 - denominator * inv;
|
||||
inv *= 2 - denominator * inv;
|
||||
|
||||
result = prod0 * inv;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @title FixedPoint96
|
||||
/// @notice Math library for fixed point arithmetic with 96 bits of precision
|
||||
library FixedPoint96 {
|
||||
uint8 internal constant RESOLUTION = 96;
|
||||
uint256 internal constant Q96 = 0x1000000000000000000000000;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user