// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.5.16; import "./CarefulMath.sol"; /** * @title Exponential module for storing fixed-precision decimals * @author Compound * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: * `Exp({mantissa: 5100000000000000000})`. */ contract Exponential is CarefulMath { uint256 constant expScale = 1e18; uint256 constant doubleScale = 1e36; uint256 constant halfExpScale = expScale / 2; uint256 constant mantissaOne = expScale; struct Exp { uint256 mantissa; } struct Double { uint256 mantissa; } /** * @dev Creates an exponential from numerator and denominator values. * Note: Returns an error if (`num` * 10e18) > MAX_INT, * or if `denom` is zero. */ function getExp(uint256 num, uint256 denom) internal pure returns (MathError, Exp memory) { (MathError err0, uint256 scaledNumerator) = mulUInt(num, expScale); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } (MathError err1, uint256 rational) = divUInt(scaledNumerator, denom); if (err1 != MathError.NO_ERROR) { return (err1, Exp({mantissa: 0})); } return (MathError.NO_ERROR, Exp({mantissa: rational})); } /** * @dev Adds two exponentials, returning a new exponential. */ function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError error, uint256 result) = addUInt(a.mantissa, b.mantissa); return (error, Exp({mantissa: result})); } /** * @dev Subtracts two exponentials, returning a new exponential. */ function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError error, uint256 result) = subUInt(a.mantissa, b.mantissa); return (error, Exp({mantissa: result})); } /** * @dev Multiply an Exp by a scalar, returning a new Exp. */ function mulScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) { (MathError err0, uint256 scaledMantissa) = mulUInt(a.mantissa, scalar); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa})); } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mulScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (MathError, uint256) { (MathError err, Exp memory product) = mulScalar(a, scalar); if (err != MathError.NO_ERROR) { return (err, 0); } return (MathError.NO_ERROR, truncate(product)); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mulScalarTruncateAddUInt( Exp memory a, uint256 scalar, uint256 addend ) internal pure returns (MathError, uint256) { (MathError err, Exp memory product) = mulScalar(a, scalar); if (err != MathError.NO_ERROR) { return (err, 0); } return addUInt(truncate(product), addend); } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) { Exp memory product = mul_(a, scalar); return truncate(product); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mul_ScalarTruncateAddUInt( Exp memory a, uint256 scalar, uint256 addend ) internal pure returns (uint256) { Exp memory product = mul_(a, scalar); return add_(truncate(product), addend); } /** * @dev Divide an Exp by a scalar, returning a new Exp. */ function divScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) { (MathError err0, uint256 descaledMantissa) = divUInt(a.mantissa, scalar); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa})); } /** * @dev Divide a scalar by an Exp, returning a new Exp. */ function divScalarByExp(uint256 scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) { /* We are doing this as: getExp(mulUInt(expScale, scalar), divisor.mantissa) How it works: Exp = a / b; Scalar = s; `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale` */ (MathError err0, uint256 numerator) = mulUInt(expScale, scalar); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } return getExp(numerator, divisor.mantissa); } /** * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer. */ function divScalarByExpTruncate(uint256 scalar, Exp memory divisor) internal pure returns (MathError, uint256) { (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor); if (err != MathError.NO_ERROR) { return (err, 0); } return (MathError.NO_ERROR, truncate(fraction)); } /** * @dev Divide a scalar by an Exp, returning a new Exp. */ function div_ScalarByExp(uint256 scalar, Exp memory divisor) internal pure returns (Exp memory) { /* We are doing this as: getExp(mulUInt(expScale, scalar), divisor.mantissa) How it works: Exp = a / b; Scalar = s; `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale` */ uint256 numerator = mul_(expScale, scalar); return Exp({mantissa: div_(numerator, divisor)}); } /** * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer. */ function div_ScalarByExpTruncate(uint256 scalar, Exp memory divisor) internal pure returns (uint256) { Exp memory fraction = div_ScalarByExp(scalar, divisor); return truncate(fraction); } /** * @dev Multiplies two exponentials, returning a new exponential. */ function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError err0, uint256 doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } // We add half the scale before dividing so that we get rounding instead of truncation. // See "Listing 6" and text above it at https://accu.org/index.php/journals/1717 // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18. (MathError err1, uint256 doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct); if (err1 != MathError.NO_ERROR) { return (err1, Exp({mantissa: 0})); } (MathError err2, uint256 product) = divUInt(doubleScaledProductWithHalfScale, expScale); // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero. assert(err2 == MathError.NO_ERROR); return (MathError.NO_ERROR, Exp({mantissa: product})); } /** * @dev Multiplies two exponentials given their mantissas, returning a new exponential. */ function mulExp(uint256 a, uint256 b) internal pure returns (MathError, Exp memory) { return mulExp(Exp({mantissa: a}), Exp({mantissa: b})); } /** * @dev Multiplies three exponentials, returning a new exponential. */ function mulExp3( Exp memory a, Exp memory b, Exp memory c ) internal pure returns (MathError, Exp memory) { (MathError err, Exp memory ab) = mulExp(a, b); if (err != MathError.NO_ERROR) { return (err, ab); } return mulExp(ab, c); } /** * @dev Divides two exponentials, returning a new exponential. * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b, * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa) */ function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { return getExp(a.mantissa, b.mantissa); } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) internal pure returns (uint256) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } /** * @dev Checks if first Exp is less than second Exp. */ function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) { return left.mantissa < right.mantissa; } /** * @dev Checks if left Exp <= right Exp. */ function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) { return left.mantissa <= right.mantissa; } /** * @dev returns true if Exp is exactly zero */ function isZeroExp(Exp memory value) internal pure returns (bool) { return value.mantissa == 0; } function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) { require(n < 2**224, errorMessage); return uint224(n); } function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) { return Exp({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(Double memory a, Double memory b) internal pure returns (Double memory) { return Double({mantissa: add_(a.mantissa, b.mantissa)}); } function add_(uint256 a, uint256 b) internal pure returns (uint256) { return add_(a, b, "addition overflow"); } function add_( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, errorMessage); return c; } function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) { return Exp({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(Double memory a, Double memory b) internal pure returns (Double memory) { return Double({mantissa: sub_(a.mantissa, b.mantissa)}); } function sub_(uint256 a, uint256 b) internal pure returns (uint256) { return sub_(a, b, "subtraction underflow"); } function sub_( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale}); } function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b)}); } function mul_(uint256 a, Exp memory b) internal pure returns (uint256) { return mul_(a, b.mantissa) / expScale; } function mul_(Double memory a, Double memory b) internal pure returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale}); } function mul_(Double memory a, uint256 b) internal pure returns (Double memory) { return Double({mantissa: mul_(a.mantissa, b)}); } function mul_(uint256 a, Double memory b) internal pure returns (uint256) { return mul_(a, b.mantissa) / doubleScale; } function mul_(uint256 a, uint256 b) internal pure returns (uint256) { return mul_(a, b, "multiplication overflow"); } function mul_( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { if (a == 0 || b == 0) { return 0; } uint256 c = a * b; require(c / a == b, errorMessage); return c; } function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) { return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)}); } function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) { return Exp({mantissa: div_(a.mantissa, b)}); } function div_(uint256 a, Exp memory b) internal pure returns (uint256) { return div_(mul_(a, expScale), b.mantissa); } function div_(Double memory a, Double memory b) internal pure returns (Double memory) { return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)}); } function div_(Double memory a, uint256 b) internal pure returns (Double memory) { return Double({mantissa: div_(a.mantissa, b)}); } function div_(uint256 a, Double memory b) internal pure returns (uint256) { return div_(mul_(a, doubleScale), b.mantissa); } function div_(uint256 a, uint256 b) internal pure returns (uint256) { return div_(a, b, "divide by zero"); } function div_( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } function fraction(uint256 a, uint256 b) internal pure returns (Double memory) { return Double({mantissa: div_(mul_(a, doubleScale), b)}); } // implementation from https://github.com/Uniswap/uniswap-lib/commit/99f3f28770640ba1bb1ff460ac7c5292fb8291a0 // original implementation: https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687 function sqrt(uint256 x) internal pure returns (uint256) { if (x == 0) return 0; uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return (r < r1 ? r : r1); } }