// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.15; import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; /** * @title SafeMathInt * @dev Math operations for int256 with overflow safety checks. */ library SafeMathInt { int256 private constant MIN_INT256 = int256(1) << 255; int256 private constant MAX_INT256 = ~(int256(1) << 255); /** * @dev Multiplies two int256 variables and fails on overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { int256 c = a * b; // Detect overflow when multiplying MIN_INT256 with -1 require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256)); require((b == 0) || (c / b == a)); return c; } /** * @dev Division of two int256 variables and fails on overflow. */ function div(int256 a, int256 b) internal pure returns (int256) { // Prevent overflow when dividing MIN_INT256 by -1 require(b != -1 || a != MIN_INT256); // Solidity already throws when dividing by 0. return a / b; } /** * @dev Subtracts two int256 variables and fails on overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a)); return c; } /** * @dev Adds two int256 variables and fails on overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a)); return c; } /** * @dev Converts to absolute value, and fails on overflow. */ function abs(int256 a) internal pure returns (int256) { require(a != MIN_INT256); return a < 0 ? -a : a; } /** * @dev Computes 2^exp with limited precision where -100 <= exp <= 100 * one * @param one 1.0 represented in the same fixed point number format as exp * @param exp The power to raise 2 to -100 <= exp <= 100 * one * @return 2^exp represented with same number of decimals after the point as one */ function twoPower(int256 exp, int256 one) internal pure returns (int256) { bool reciprocal = false; if (exp < 0) { reciprocal = true; exp = abs(exp); } // Precomputed values for 2^(1/2^i) in 18 decimals fixed point numbers int256[5] memory ks = [ int256(1414213562373095049), 1189207115002721067, 1090507732665257659, 1044273782427413840, 1021897148654116678 ]; int256 whole = div(exp, one); require(whole <= 100); int256 result = mul(int256(uint256(1) << uint256(whole)), one); int256 remaining = sub(exp, mul(whole, one)); int256 current = div(one, 2); for (uint256 i = 0; i < 5; i++) { if (remaining >= current) { remaining = sub(remaining, current); result = div(mul(result, ks[i]), 10**18); // 10**18 to match hardcoded ks values } current = div(current, 2); } if (reciprocal) { result = div(mul(one, one), result); } return result; } }