91 lines
4.0 KiB
Solidity
91 lines
4.0 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.36;
|
|
|
|
import {Test} from "forge-std/Test.sol";
|
|
import {TickMath} from "../src/libraries/TickMath.sol";
|
|
import {SqrtPriceMath} from "../src/libraries/SqrtPriceMath.sol";
|
|
import {SwapMath} from "../src/libraries/SwapMath.sol";
|
|
import {FullMath} from "../src/libraries/FullMath.sol";
|
|
|
|
contract ClMathTest is Test {
|
|
uint160 private constant priceAtTickZero = 79228162514264337593543950336;
|
|
|
|
function testSqrtRatioAtKnownTicks() public pure {
|
|
assertEq(TickMath.getSqrtRatioAtTick(0), priceAtTickZero);
|
|
assertEq(TickMath.getSqrtRatioAtTick(TickMath.minTick), TickMath.minSqrtRatio);
|
|
assertEq(TickMath.getSqrtRatioAtTick(TickMath.maxTick), TickMath.maxSqrtRatio);
|
|
}
|
|
|
|
function testTickAtKnownRatios() public pure {
|
|
assertEq(TickMath.getTickAtSqrtRatio(priceAtTickZero), 0);
|
|
assertEq(TickMath.getTickAtSqrtRatio(TickMath.minSqrtRatio), TickMath.minTick);
|
|
}
|
|
|
|
function testSqrtRatioMonotonic() public pure {
|
|
assertGt(TickMath.getSqrtRatioAtTick(1), TickMath.getSqrtRatioAtTick(0));
|
|
assertLt(TickMath.getSqrtRatioAtTick(-1), TickMath.getSqrtRatioAtTick(0));
|
|
assertGt(TickMath.getSqrtRatioAtTick(500000), TickMath.getSqrtRatioAtTick(499999));
|
|
}
|
|
|
|
function testFuzzTickRoundTrip(int24 tick) public pure {
|
|
tick = int24(bound(tick, TickMath.minTick, TickMath.maxTick));
|
|
uint160 ratio = TickMath.getSqrtRatioAtTick(tick);
|
|
if (ratio >= TickMath.maxSqrtRatio) return;
|
|
int24 recovered = TickMath.getTickAtSqrtRatio(ratio);
|
|
assertEq(recovered, tick);
|
|
}
|
|
|
|
function testFuzzTickAtRatioWithinBounds(uint160 ratio) public pure {
|
|
ratio = uint160(bound(ratio, TickMath.minSqrtRatio, TickMath.maxSqrtRatio - 1));
|
|
int24 tick = TickMath.getTickAtSqrtRatio(ratio);
|
|
assertGe(TickMath.getSqrtRatioAtTick(tick), TickMath.minSqrtRatio == 0 ? 0 : 0);
|
|
assertLe(TickMath.getSqrtRatioAtTick(tick), ratio);
|
|
assertGt(TickMath.getSqrtRatioAtTick(tick + 1), ratio);
|
|
}
|
|
|
|
function testAmount1DeltaKnown() public pure {
|
|
uint160 a = TickMath.getSqrtRatioAtTick(0);
|
|
uint160 b = TickMath.getSqrtRatioAtTick(120);
|
|
uint256 delta = SqrtPriceMath.getAmount1Delta(a, b, 1e18, false);
|
|
assertEq(delta, FullMath.mulDiv(1e18, b - a, 0x1000000000000000000000000));
|
|
}
|
|
|
|
function testAmount0DeltaSymmetric() public pure {
|
|
uint160 a = TickMath.getSqrtRatioAtTick(-60);
|
|
uint160 b = TickMath.getSqrtRatioAtTick(60);
|
|
uint256 up = SqrtPriceMath.getAmount0Delta(a, b, 5e18, true);
|
|
uint256 down = SqrtPriceMath.getAmount0Delta(a, b, 5e18, false);
|
|
assertGe(up, down);
|
|
assertLe(up - down, 1);
|
|
}
|
|
|
|
function testComputeSwapStepExactInReachesTarget() public pure {
|
|
uint160 current = TickMath.getSqrtRatioAtTick(0);
|
|
uint160 target = TickMath.getSqrtRatioAtTick(-600);
|
|
(uint160 next, uint256 amountIn, uint256 amountOut, uint256 feeAmount) =
|
|
SwapMath.computeSwapStep(current, target, 1e21, 1e24, 3000);
|
|
assertEq(next, target);
|
|
assertGt(amountIn, 0);
|
|
assertGt(amountOut, 0);
|
|
assertGt(feeAmount, 0);
|
|
}
|
|
|
|
function testComputeSwapStepPartialFill() public pure {
|
|
uint160 current = TickMath.getSqrtRatioAtTick(0);
|
|
uint160 target = TickMath.getSqrtRatioAtTick(-600);
|
|
(uint160 next,, uint256 amountOut,) = SwapMath.computeSwapStep(current, target, 1e21, 1e15, 3000);
|
|
assertGt(next, target);
|
|
assertLt(next, current);
|
|
assertGt(amountOut, 0);
|
|
}
|
|
|
|
function testFuzzComputeSwapStepFeeBound(uint128 liquidity, uint128 amount) public pure {
|
|
liquidity = uint128(bound(liquidity, 1e12, 1e30));
|
|
int256 amountIn = int256(uint256(bound(amount, 1, 1e30)));
|
|
uint160 current = TickMath.getSqrtRatioAtTick(0);
|
|
uint160 target = TickMath.getSqrtRatioAtTick(-887000);
|
|
(, uint256 stepIn,, uint256 feeAmount) = SwapMath.computeSwapStep(current, target, liquidity, amountIn, 3000);
|
|
assertLe(stepIn + feeAmount, uint256(amountIn));
|
|
}
|
|
}
|