// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.7.6; pragma abicoder v2; import { FixedPoint96 } from "@uniswap/v3-core/contracts/libraries/FixedPoint96.sol"; import { FullMath } from "@uniswap/v3-core/contracts/libraries/FullMath.sol"; import { PerpSafeCast } from "./PerpSafeCast.sol"; import { MathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/MathUpgradeable.sol"; import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; import { SignedSafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SignedSafeMathUpgradeable.sol"; library PerpMath { using PerpSafeCast for int256; using SignedSafeMathUpgradeable for int256; using SafeMathUpgradeable for uint256; function formatSqrtPriceX96ToPriceX96(uint160 sqrtPriceX96) internal pure returns (uint256) { return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96); } function formatX10_18ToX96(uint256 valueX10_18) internal pure returns (uint256) { return FullMath.mulDiv(valueX10_18, FixedPoint96.Q96, 1 ether); } function formatX96ToX10_18(uint256 valueX96) internal pure returns (uint256) { return FullMath.mulDiv(valueX96, 1 ether, FixedPoint96.Q96); } function max(int256 a, int256 b) internal pure returns (int256) { return a >= b ? a : b; } function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } function abs(int256 value) internal pure returns (uint256) { return value >= 0 ? value.toUint256() : neg256(value).toUint256(); } function neg256(int256 a) internal pure returns (int256) { require(a > -2**255, "PerpMath: inversion overflow"); return -a; } function neg256(uint256 a) internal pure returns (int256) { return -PerpSafeCast.toInt256(a); } function neg128(int128 a) internal pure returns (int128) { require(a > -2**127, "PerpMath: inversion overflow"); return -a; } function neg128(uint128 a) internal pure returns (int128) { return -PerpSafeCast.toInt128(a); } function divBy10_18(int256 value) internal pure returns (int256) { // no overflow here return value / (1 ether); } function divBy10_18(uint256 value) internal pure returns (uint256) { // no overflow here return value / (1 ether); } function subRatio(uint24 a, uint24 b) internal pure returns (uint24) { require(b <= a, "PerpMath: subtraction overflow"); return a - b; } function mulRatio(uint256 value, uint24 ratio) internal pure returns (uint256) { return FullMath.mulDiv(value, ratio, 1e6); } function mulRatio(int256 value, uint24 ratio) internal pure returns (int256) { return mulDiv(value, int256(ratio), 1e6); } function divRatio(uint256 value, uint24 ratio) internal pure returns (uint256) { return FullMath.mulDiv(value, 1e6, ratio); } /// @param denominator cannot be 0 and is checked in FullMath.mulDiv() function mulDiv( int256 a, int256 b, uint256 denominator ) internal pure returns (int256 result) { uint256 unsignedA = a < 0 ? uint256(neg256(a)) : uint256(a); uint256 unsignedB = b < 0 ? uint256(neg256(b)) : uint256(b); bool negative = ((a < 0 && b > 0) || (a > 0 && b < 0)) ? true : false; uint256 unsignedResult = FullMath.mulDiv(unsignedA, unsignedB, denominator); result = negative ? neg256(unsignedResult) : PerpSafeCast.toInt256(unsignedResult); return result; } function findMedianOfThree( uint256 v1, uint256 v2, uint256 v3 ) internal pure returns (uint256) { return MathUpgradeable.max(MathUpgradeable.min(v1, v2), MathUpgradeable.min(MathUpgradeable.max(v1, v2), v3)); } }