// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import"../Common.sol"asCommon;
import"./Errors.sol"asCastingErrors;
import { SD59x18 } from"../sd59x18/ValueType.sol";
import { UD2x18 } from"../ud2x18/ValueType.sol";
import { UD60x18 } from"../ud60x18/ValueType.sol";
import { SD1x18 } from"./ValueType.sol";
/// @notice Casts an SD1x18 number into SD59x18./// @dev There is no overflow check because the domain of SD1x18 is a subset of SD59x18.functionintoSD59x18(SD1x18 x) purereturns (SD59x18 result) {
result = SD59x18.wrap(int256(SD1x18.unwrap(x)));
}
/// @notice Casts an SD1x18 number into UD2x18./// - x must be positive.functionintoUD2x18(SD1x18 x) purereturns (UD2x18 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt <0) {
revert CastingErrors.PRBMath_SD1x18_ToUD2x18_Underflow(x);
}
result = UD2x18.wrap(uint64(xInt));
}
/// @notice Casts an SD1x18 number into UD60x18./// @dev Requirements:/// - x must be positive.functionintoUD60x18(SD1x18 x) purereturns (UD60x18 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt <0) {
revert CastingErrors.PRBMath_SD1x18_ToUD60x18_Underflow(x);
}
result = UD60x18.wrap(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint256./// @dev Requirements:/// - x must be positive.functionintoUint256(SD1x18 x) purereturns (uint256 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt <0) {
revert CastingErrors.PRBMath_SD1x18_ToUint256_Underflow(x);
}
result =uint256(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint128./// @dev Requirements:/// - x must be positive.functionintoUint128(SD1x18 x) purereturns (uint128 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt <0) {
revert CastingErrors.PRBMath_SD1x18_ToUint128_Underflow(x);
}
result =uint128(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint40./// @dev Requirements:/// - x must be positive./// - x must be less than or equal to `MAX_UINT40`.functionintoUint40(SD1x18 x) purereturns (uint40 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt <0) {
revert CastingErrors.PRBMath_SD1x18_ToUint40_Underflow(x);
}
if (xInt >int64(uint64(Common.MAX_UINT40))) {
revert CastingErrors.PRBMath_SD1x18_ToUint40_Overflow(x);
}
result =uint40(uint64(xInt));
}
/// @notice Alias for {wrap}.functionsd1x18(int64 x) purereturns (SD1x18 result) {
result = SD1x18.wrap(x);
}
/// @notice Unwraps an SD1x18 number into int64.functionunwrap(SD1x18 x) purereturns (int64 result) {
result = SD1x18.unwrap(x);
}
/// @notice Wraps an int64 number into SD1x18.functionwrap(int64 x) purereturns (SD1x18 result) {
result = SD1x18.wrap(x);
}
Contract Source Code
File 4 of 19: Common.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;// Common.sol//// Common mathematical functions needed by both SD59x18 and UD60x18. Note that these global functions do not// always operate with SD59x18 and UD60x18 numbers./*//////////////////////////////////////////////////////////////////////////
CUSTOM ERRORS
//////////////////////////////////////////////////////////////////////////*//// @notice Thrown when the resultant value in {mulDiv} overflows uint256.errorPRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator);
/// @notice Thrown when the resultant value in {mulDiv18} overflows uint256.errorPRBMath_MulDiv18_Overflow(uint256 x, uint256 y);
/// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`.errorPRBMath_MulDivSigned_InputTooSmall();
/// @notice Thrown when the resultant value in {mulDivSigned} overflows int256.errorPRBMath_MulDivSigned_Overflow(int256 x, int256 y);
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*//// @dev The maximum value a uint128 number can have.uint128constant MAX_UINT128 =type(uint128).max;
/// @dev The maximum value a uint40 number can have.uint40constant MAX_UINT40 =type(uint40).max;
/// @dev The unit number, which the decimal precision of the fixed-point types.uint256constant UNIT =1e18;
/// @dev The unit number inverted mod 2^256.uint256constant UNIT_INVERSE =78156646155174841979727994598816262306175212592076161876661_508869554232690281;
/// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant/// bit in the binary representation of `UNIT`.uint256constant UNIT_LPOTD =262144;
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*//// @notice Calculates the binary exponent of x using the binary fraction method./// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693./// @param x The exponent as an unsigned 192.64-bit fixed-point number./// @return result The result as an unsigned 60.18-decimal fixed-point number./// @custom:smtchecker abstract-function-nondetfunctionexp2(uint256 x) purereturns (uint256 result) {
unchecked {
// Start from 0.5 in the 192.64-bit fixed-point format.
result =0x800000000000000000000000000000000000000000000000;
// The following logic multiplies the result by $\sqrt{2^{-i}}$ when the bit at position i is 1. Key points://// 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65.// 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing// a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1,// we know that `x & 0xFF` is also 1.if (x &0xFF00000000000000>0) {
if (x &0x8000000000000000>0) {
result = (result *0x16A09E667F3BCC909) >>64;
}
if (x &0x4000000000000000>0) {
result = (result *0x1306FE0A31B7152DF) >>64;
}
if (x &0x2000000000000000>0) {
result = (result *0x1172B83C7D517ADCE) >>64;
}
if (x &0x1000000000000000>0) {
result = (result *0x10B5586CF9890F62A) >>64;
}
if (x &0x800000000000000>0) {
result = (result *0x1059B0D31585743AE) >>64;
}
if (x &0x400000000000000>0) {
result = (result *0x102C9A3E778060EE7) >>64;
}
if (x &0x200000000000000>0) {
result = (result *0x10163DA9FB33356D8) >>64;
}
if (x &0x100000000000000>0) {
result = (result *0x100B1AFA5ABCBED61) >>64;
}
}
if (x &0xFF000000000000>0) {
if (x &0x80000000000000>0) {
result = (result *0x10058C86DA1C09EA2) >>64;
}
if (x &0x40000000000000>0) {
result = (result *0x1002C605E2E8CEC50) >>64;
}
if (x &0x20000000000000>0) {
result = (result *0x100162F3904051FA1) >>64;
}
if (x &0x10000000000000>0) {
result = (result *0x1000B175EFFDC76BA) >>64;
}
if (x &0x8000000000000>0) {
result = (result *0x100058BA01FB9F96D) >>64;
}
if (x &0x4000000000000>0) {
result = (result *0x10002C5CC37DA9492) >>64;
}
if (x &0x2000000000000>0) {
result = (result *0x1000162E525EE0547) >>64;
}
if (x &0x1000000000000>0) {
result = (result *0x10000B17255775C04) >>64;
}
}
if (x &0xFF0000000000>0) {
if (x &0x800000000000>0) {
result = (result *0x1000058B91B5BC9AE) >>64;
}
if (x &0x400000000000>0) {
result = (result *0x100002C5C89D5EC6D) >>64;
}
if (x &0x200000000000>0) {
result = (result *0x10000162E43F4F831) >>64;
}
if (x &0x100000000000>0) {
result = (result *0x100000B1721BCFC9A) >>64;
}
if (x &0x80000000000>0) {
result = (result *0x10000058B90CF1E6E) >>64;
}
if (x &0x40000000000>0) {
result = (result *0x1000002C5C863B73F) >>64;
}
if (x &0x20000000000>0) {
result = (result *0x100000162E430E5A2) >>64;
}
if (x &0x10000000000>0) {
result = (result *0x1000000B172183551) >>64;
}
}
if (x &0xFF00000000>0) {
if (x &0x8000000000>0) {
result = (result *0x100000058B90C0B49) >>64;
}
if (x &0x4000000000>0) {
result = (result *0x10000002C5C8601CC) >>64;
}
if (x &0x2000000000>0) {
result = (result *0x1000000162E42FFF0) >>64;
}
if (x &0x1000000000>0) {
result = (result *0x10000000B17217FBB) >>64;
}
if (x &0x800000000>0) {
result = (result *0x1000000058B90BFCE) >>64;
}
if (x &0x400000000>0) {
result = (result *0x100000002C5C85FE3) >>64;
}
if (x &0x200000000>0) {
result = (result *0x10000000162E42FF1) >>64;
}
if (x &0x100000000>0) {
result = (result *0x100000000B17217F8) >>64;
}
}
if (x &0xFF000000>0) {
if (x &0x80000000>0) {
result = (result *0x10000000058B90BFC) >>64;
}
if (x &0x40000000>0) {
result = (result *0x1000000002C5C85FE) >>64;
}
if (x &0x20000000>0) {
result = (result *0x100000000162E42FF) >>64;
}
if (x &0x10000000>0) {
result = (result *0x1000000000B17217F) >>64;
}
if (x &0x8000000>0) {
result = (result *0x100000000058B90C0) >>64;
}
if (x &0x4000000>0) {
result = (result *0x10000000002C5C860) >>64;
}
if (x &0x2000000>0) {
result = (result *0x1000000000162E430) >>64;
}
if (x &0x1000000>0) {
result = (result *0x10000000000B17218) >>64;
}
}
if (x &0xFF0000>0) {
if (x &0x800000>0) {
result = (result *0x1000000000058B90C) >>64;
}
if (x &0x400000>0) {
result = (result *0x100000000002C5C86) >>64;
}
if (x &0x200000>0) {
result = (result *0x10000000000162E43) >>64;
}
if (x &0x100000>0) {
result = (result *0x100000000000B1721) >>64;
}
if (x &0x80000>0) {
result = (result *0x10000000000058B91) >>64;
}
if (x &0x40000>0) {
result = (result *0x1000000000002C5C8) >>64;
}
if (x &0x20000>0) {
result = (result *0x100000000000162E4) >>64;
}
if (x &0x10000>0) {
result = (result *0x1000000000000B172) >>64;
}
}
if (x &0xFF00>0) {
if (x &0x8000>0) {
result = (result *0x100000000000058B9) >>64;
}
if (x &0x4000>0) {
result = (result *0x10000000000002C5D) >>64;
}
if (x &0x2000>0) {
result = (result *0x1000000000000162E) >>64;
}
if (x &0x1000>0) {
result = (result *0x10000000000000B17) >>64;
}
if (x &0x800>0) {
result = (result *0x1000000000000058C) >>64;
}
if (x &0x400>0) {
result = (result *0x100000000000002C6) >>64;
}
if (x &0x200>0) {
result = (result *0x10000000000000163) >>64;
}
if (x &0x100>0) {
result = (result *0x100000000000000B1) >>64;
}
}
if (x &0xFF>0) {
if (x &0x80>0) {
result = (result *0x10000000000000059) >>64;
}
if (x &0x40>0) {
result = (result *0x1000000000000002C) >>64;
}
if (x &0x20>0) {
result = (result *0x10000000000000016) >>64;
}
if (x &0x10>0) {
result = (result *0x1000000000000000B) >>64;
}
if (x &0x8>0) {
result = (result *0x10000000000000006) >>64;
}
if (x &0x4>0) {
result = (result *0x10000000000000003) >>64;
}
if (x &0x2>0) {
result = (result *0x10000000000000001) >>64;
}
if (x &0x1>0) {
result = (result *0x10000000000000001) >>64;
}
}
// In the code snippet below, two operations are executed simultaneously://// 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1// accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192.// 2. The result is then converted to an unsigned 60.18-decimal fixed-point format.//// The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the,// integer part, $2^n$.
result *= UNIT;
result >>= (191- (x >>64));
}
}
/// @notice Finds the zero-based index of the first 1 in the binary representation of x.////// @dev See the note on "msb" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set////// Each step in this implementation is equivalent to this high-level code:////// ```solidity/// if (x >= 2 ** 128) {/// x >>= 128;/// result += 128;/// }/// ```////// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here:/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948////// The Yul instructions used below are:////// - "gt" is "greater than"/// - "or" is the OR bitwise operator/// - "shl" is "shift left"/// - "shr" is "shift right"////// @param x The uint256 number for which to find the index of the most significant bit./// @return result The index of the most significant bit as a uint256./// @custom:smtchecker abstract-function-nondetfunctionmsb(uint256 x) purereturns (uint256 result) {
// 2^128assembly ("memory-safe") {
let factor :=shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^64assembly ("memory-safe") {
let factor :=shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^32assembly ("memory-safe") {
let factor :=shl(5, gt(x, 0xFFFFFFFF))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^16assembly ("memory-safe") {
let factor :=shl(4, gt(x, 0xFFFF))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^8assembly ("memory-safe") {
let factor :=shl(3, gt(x, 0xFF))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^4assembly ("memory-safe") {
let factor :=shl(2, gt(x, 0xF))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^2assembly ("memory-safe") {
let factor :=shl(1, gt(x, 0x3))
x :=shr(factor, x)
result :=or(result, factor)
}
// 2^1// No need to shift x any more.assembly ("memory-safe") {
let factor :=gt(x, 0x1)
result :=or(result, factor)
}
}
/// @notice Calculates x*y÷denominator with 512-bit precision.////// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.////// Notes:/// - The result is rounded toward zero.////// Requirements:/// - The denominator must not be zero./// - The result must fit in uint256.////// @param x The multiplicand as a uint256./// @param y The multiplier as a uint256./// @param denominator The divisor as a uint256./// @return result The result as a uint256./// @custom:smtchecker abstract-function-nondetfunctionmulDiv(uint256 x, uint256 y, uint256 denominator) purereturns (uint256 result) {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use// use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256// variables such that product = prod1 * 2^256 + prod0.uint256 prod0; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly ("memory-safe") {
let mm :=mulmod(x, y, not(0))
prod0 :=mul(x, y)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.if (prod1 ==0) {
unchecked {
return prod0 / denominator;
}
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.if (prod1 >= denominator) {
revert PRBMath_MulDiv_Overflow(x, y, denominator);
}
////////////////////////////////////////////////////////////////////////////// 512 by 256 division////////////////////////////////////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0].uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using the mulmod Yul instruction.
remainder :=mulmod(x, y, denominator)
// Subtract 256 bit number from 512-bit number.
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
unchecked {
// Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow// because the denominator cannot be zero at this point in the function execution. The result is always >= 1.// For more detail, see https://cs.stackexchange.com/q/138556/92363.uint256 lpotdod = denominator & (~denominator +1);
uint256 flippedLpotdod;
assembly ("memory-safe") {
// Factor powers of two out of denominator.
denominator :=div(denominator, lpotdod)
// Divide [prod1 prod0] by lpotdod.
prod0 :=div(prod0, lpotdod)
// Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one.// `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits.// However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693
flippedLpotdod :=add(div(sub(0, lpotdod), lpotdod), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * flippedLpotdod;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for// four bits. That is, denominator * inv = 1 mod 2^4.uint256 inverse = (3* denominator) ^2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works// in modular arithmetic, doubling the correct bits in each step.
inverse *=2- denominator * inverse; // inverse mod 2^8
inverse *=2- denominator * inverse; // inverse mod 2^16
inverse *=2- denominator * inverse; // inverse mod 2^32
inverse *=2- denominator * inverse; // inverse mod 2^64
inverse *=2- denominator * inverse; // inverse mod 2^128
inverse *=2- denominator * inverse; // inverse mod 2^256// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inverse;
}
}
/// @notice Calculates x*y÷1e18 with 512-bit precision.////// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18.////// Notes:/// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}./// - The result is rounded toward zero./// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations:////// $$/// \begin{cases}/// x * y = MAX\_UINT256 * UNIT \\/// (x * y) \% UNIT \geq \frac{UNIT}{2}/// \end{cases}/// $$////// Requirements:/// - Refer to the requirements in {mulDiv}./// - The result must fit in uint256.////// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number./// @param y The multiplier as an unsigned 60.18-decimal fixed-point number./// @return result The result as an unsigned 60.18-decimal fixed-point number./// @custom:smtchecker abstract-function-nondetfunctionmulDiv18(uint256 x, uint256 y) purereturns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly ("memory-safe") {
let mm :=mulmod(x, y, not(0))
prod0 :=mul(x, y)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 ==0) {
unchecked {
return prod0 / UNIT;
}
}
if (prod1 >= UNIT) {
revert PRBMath_MulDiv18_Overflow(x, y);
}
uint256 remainder;
assembly ("memory-safe") {
remainder :=mulmod(x, y, UNIT)
result :=mul(
or(
div(sub(prod0, remainder), UNIT_LPOTD),
mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1))
),
UNIT_INVERSE
)
}
}
/// @notice Calculates x*y÷denominator with 512-bit precision.////// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately.////// Notes:/// - The result is rounded toward zero.////// Requirements:/// - Refer to the requirements in {mulDiv}./// - None of the inputs can be `type(int256).min`./// - The result must fit in int256.////// @param x The multiplicand as an int256./// @param y The multiplier as an int256./// @param denominator The divisor as an int256./// @return result The result as an int256./// @custom:smtchecker abstract-function-nondetfunctionmulDivSigned(int256 x, int256 y, int256 denominator) purereturns (int256 result) {
if (x ==type(int256).min|| y ==type(int256).min|| denominator ==type(int256).min) {
revert PRBMath_MulDivSigned_InputTooSmall();
}
// Get hold of the absolute values of x, y and the denominator.uint256 xAbs;
uint256 yAbs;
uint256 dAbs;
unchecked {
xAbs = x <0 ? uint256(-x) : uint256(x);
yAbs = y <0 ? uint256(-y) : uint256(y);
dAbs = denominator <0 ? uint256(-denominator) : uint256(denominator);
}
// Compute the absolute value of x*y÷denominator. The result must fit in int256.uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs);
if (resultAbs >uint256(type(int256).max)) {
revert PRBMath_MulDivSigned_Overflow(x, y);
}
// Get the signs of x, y and the denominator.uint256 sx;
uint256 sy;
uint256 sd;
assembly ("memory-safe") {
// "sgt" is the "signed greater than" assembly instruction and "sub(0,1)" is -1 in two's complement.
sx :=sgt(x, sub(0, 1))
sy :=sgt(y, sub(0, 1))
sd :=sgt(denominator, sub(0, 1))
}
// XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs.// If there are, the result should be negative. Otherwise, it should be positive.unchecked {
result = sx ^ sy ^ sd ==0 ? -int256(resultAbs) : int256(resultAbs);
}
}
/// @notice Calculates the square root of x using the Babylonian method.////// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.////// Notes:/// - If x is not a perfect square, the result is rounded down./// - Credits to OpenZeppelin for the explanations in comments below.////// @param x The uint256 number for which to calculate the square root./// @return result The result as a uint256./// @custom:smtchecker abstract-function-nondetfunctionsqrt(uint256 x) purereturns (uint256 result) {
if (x ==0) {
return0;
}
// For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x.//// We know that the "msb" (most significant bit) of x is a power of 2 such that we have://// $$// msb(x) <= x <= 2*msb(x)$// $$//// We write $msb(x)$ as $2^k$, and we get://// $$// k = log_2(x)// $$//// Thus, we can write the initial inequality as://// $$// 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\// sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\// 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1}// $$//// Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit.uint256 xAux =uint256(x);
result =1;
if (xAux >=2**128) {
xAux >>=128;
result <<=64;
}
if (xAux >=2**64) {
xAux >>=64;
result <<=32;
}
if (xAux >=2**32) {
xAux >>=32;
result <<=16;
}
if (xAux >=2**16) {
xAux >>=16;
result <<=8;
}
if (xAux >=2**8) {
xAux >>=8;
result <<=4;
}
if (xAux >=2**4) {
xAux >>=4;
result <<=2;
}
if (xAux >=2**2) {
result <<=1;
}
// At this point, `result` is an estimation with at least one bit of precision. We know the true value has at// most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision// doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of// precision into the expected uint128 result.unchecked {
result = (result + x / result) >>1;
result = (result + x / result) >>1;
result = (result + x / result) >>1;
result = (result + x / result) >>1;
result = (result + x / result) >>1;
result = (result + x / result) >>1;
result = (result + x / result) >>1;
// If x is not a perfect square, round the result toward zero.uint256 roundedResult = x / result;
if (result >= roundedResult) {
result = roundedResult;
}
}
}
Contract Source Code
File 5 of 19: Constants.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import { UD60x18 } from"./ValueType.sol";
// NOTICE: the "u" prefix stands for "unwrapped"./// @dev Euler's number as a UD60x18 number.
UD60x18 constant E = UD60x18.wrap(2_718281828459045235);
/// @dev The maximum input permitted in {exp}.uint256constant uEXP_MAX_INPUT =133_084258667509499440;
UD60x18 constant EXP_MAX_INPUT = UD60x18.wrap(uEXP_MAX_INPUT);
/// @dev The maximum input permitted in {exp2}.uint256constant uEXP2_MAX_INPUT =192e18-1;
UD60x18 constant EXP2_MAX_INPUT = UD60x18.wrap(uEXP2_MAX_INPUT);
/// @dev Half the UNIT number.uint256constant uHALF_UNIT =0.5e18;
UD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT);
/// @dev $log_2(10)$ as a UD60x18 number.uint256constant uLOG2_10 =3_321928094887362347;
UD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10);
/// @dev $log_2(e)$ as a UD60x18 number.uint256constant uLOG2_E =1_442695040888963407;
UD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E);
/// @dev The maximum value a UD60x18 number can have.uint256constant uMAX_UD60x18 =115792089237316195423570985008687907853269984665640564039457_584007913129639935;
UD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18);
/// @dev The maximum whole value a UD60x18 number can have.uint256constant uMAX_WHOLE_UD60x18 =115792089237316195423570985008687907853269984665640564039457_000000000000000000;
UD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18);
/// @dev PI as a UD60x18 number.
UD60x18 constant PI = UD60x18.wrap(3_141592653589793238);
/// @dev The unit number, which gives the decimal precision of UD60x18.uint256constant uUNIT =1e18;
UD60x18 constant UNIT = UD60x18.wrap(uUNIT);
/// @dev The unit number squared.uint256constant uUNIT_SQUARED =1e36;
UD60x18 constant UNIT_SQUARED = UD60x18.wrap(uUNIT_SQUARED);
/// @dev Zero as a UD60x18 number.
UD60x18 constant ZERO = UD60x18.wrap(0);
Contract Source Code
File 6 of 19: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 7 of 19: Conversions.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import { uMAX_UD60x18, uUNIT } from"./Constants.sol";
import { PRBMath_UD60x18_Convert_Overflow } from"./Errors.sol";
import { UD60x18 } from"./ValueType.sol";
/// @notice Converts a UD60x18 number to a simple integer by dividing it by `UNIT`./// @dev The result is rounded toward zero./// @param x The UD60x18 number to convert./// @return result The same number in basic integer form.functionconvert(UD60x18 x) purereturns (uint256 result) {
result = UD60x18.unwrap(x) / uUNIT;
}
/// @notice Converts a simple integer to UD60x18 by multiplying it by `UNIT`.////// @dev Requirements:/// - x must be less than or equal to `MAX_UD60x18 / UNIT`.////// @param x The basic integer to convert./// @param result The same number converted to UD60x18.functionconvert(uint256 x) purereturns (UD60x18 result) {
if (x > uMAX_UD60x18 / uUNIT) {
revert PRBMath_UD60x18_Convert_Overflow(x);
}
unchecked {
result = UD60x18.wrap(x * uUNIT);
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import { SD1x18 } from"./ValueType.sol";
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD2x18.errorPRBMath_SD1x18_ToUD2x18_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD60x18.errorPRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint128.errorPRBMath_SD1x18_ToUint128_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint256.errorPRBMath_SD1x18_ToUint256_Underflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40.errorPRBMath_SD1x18_ToUint40_Overflow(SD1x18 x);
/// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40.errorPRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);
Contract Source Code
File 10 of 19: Helpers.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import { wrap } from"./Casting.sol";
import { UD60x18 } from"./ValueType.sol";
/// @notice Implements the checked addition operation (+) in the UD60x18 type.functionadd(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
result = wrap(x.unwrap() + y.unwrap());
}
/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.functionand(UD60x18 x, uint256 bits) purereturns (UD60x18 result) {
result = wrap(x.unwrap() & bits);
}
/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.functionand2(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
result = wrap(x.unwrap() & y.unwrap());
}
/// @notice Implements the equal operation (==) in the UD60x18 type.functioneq(UD60x18 x, UD60x18 y) purereturns (bool result) {
result = x.unwrap() == y.unwrap();
}
/// @notice Implements the greater than operation (>) in the UD60x18 type.functiongt(UD60x18 x, UD60x18 y) purereturns (bool result) {
result = x.unwrap() > y.unwrap();
}
/// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type.functiongte(UD60x18 x, UD60x18 y) purereturns (bool result) {
result = x.unwrap() >= y.unwrap();
}
/// @notice Implements a zero comparison check function in the UD60x18 type.functionisZero(UD60x18 x) purereturns (bool result) {
// This wouldn't work if x could be negative.
result = x.unwrap() ==0;
}
/// @notice Implements the left shift operation (<<) in the UD60x18 type.functionlshift(UD60x18 x, uint256 bits) purereturns (UD60x18 result) {
result = wrap(x.unwrap() << bits);
}
/// @notice Implements the lower than operation (<) in the UD60x18 type.functionlt(UD60x18 x, UD60x18 y) purereturns (bool result) {
result = x.unwrap() < y.unwrap();
}
/// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type.functionlte(UD60x18 x, UD60x18 y) purereturns (bool result) {
result = x.unwrap() <= y.unwrap();
}
/// @notice Implements the checked modulo operation (%) in the UD60x18 type.functionmod(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
result = wrap(x.unwrap() % y.unwrap());
}
/// @notice Implements the not equal operation (!=) in the UD60x18 type.functionneq(UD60x18 x, UD60x18 y) purereturns (bool result) {
result = x.unwrap() != y.unwrap();
}
/// @notice Implements the NOT (~) bitwise operation in the UD60x18 type.functionnot(UD60x18 x) purereturns (UD60x18 result) {
result = wrap(~x.unwrap());
}
/// @notice Implements the OR (|) bitwise operation in the UD60x18 type.functionor(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
result = wrap(x.unwrap() | y.unwrap());
}
/// @notice Implements the right shift operation (>>) in the UD60x18 type.functionrshift(UD60x18 x, uint256 bits) purereturns (UD60x18 result) {
result = wrap(x.unwrap() >> bits);
}
/// @notice Implements the checked subtraction operation (-) in the UD60x18 type.functionsub(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
result = wrap(x.unwrap() - y.unwrap());
}
/// @notice Implements the unchecked addition operation (+) in the UD60x18 type.functionuncheckedAdd(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
unchecked {
result = wrap(x.unwrap() + y.unwrap());
}
}
/// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type.functionuncheckedSub(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
unchecked {
result = wrap(x.unwrap() - y.unwrap());
}
}
/// @notice Implements the XOR (^) bitwise operation in the UD60x18 type.functionxor(UD60x18 x, UD60x18 y) purereturns (UD60x18 result) {
result = wrap(x.unwrap() ^ y.unwrap());
}
Contract Source Code
File 11 of 19: IERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address to, uint256 amount) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 amount) externalreturns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom, address to, uint256 amount) externalreturns (bool);
}
Contract Source Code
File 12 of 19: IERC20Metadata.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)pragmasolidity ^0.8.0;import"../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/interfaceIERC20MetadataisIERC20{
/**
* @dev Returns the name of the token.
*/functionname() externalviewreturns (stringmemory);
/**
* @dev Returns the symbol of the token.
*/functionsymbol() externalviewreturns (stringmemory);
/**
* @dev Returns the decimals places of the token.
*/functiondecimals() externalviewreturns (uint8);
}
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import"../Common.sol"asCommon;
import"./Errors.sol"asErrors;
import {
uEXP_MAX_INPUT,
uEXP2_MAX_INPUT,
uHALF_UNIT,
uLOG2_10,
uLOG2_E,
uMAX_SD59x18,
uMAX_WHOLE_SD59x18,
uMIN_SD59x18,
uMIN_WHOLE_SD59x18,
UNIT,
uUNIT,
uUNIT_SQUARED,
ZERO
} from"./Constants.sol";
import { wrap } from"./Helpers.sol";
import { SD59x18 } from"./ValueType.sol";
/// @notice Calculates the absolute value of x.////// @dev Requirements:/// - x must be greater than `MIN_SD59x18`.////// @param x The SD59x18 number for which to calculate the absolute value./// @param result The absolute value of x as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionabs(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt == uMIN_SD59x18) {
revert Errors.PRBMath_SD59x18_Abs_MinSD59x18();
}
result = xInt <0 ? wrap(-xInt) : x;
}
/// @notice Calculates the arithmetic average of x and y.////// @dev Notes:/// - The result is rounded toward zero.////// @param x The first operand as an SD59x18 number./// @param y The second operand as an SD59x18 number./// @return result The arithmetic average as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionavg(SD59x18 x, SD59x18 y) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
unchecked {
// This operation is equivalent to `x / 2 + y / 2`, and it can never overflow.int256 sum = (xInt >>1) + (yInt >>1);
if (sum <0) {
// If at least one of x and y is odd, add 1 to the result, because shifting negative numbers to the right// rounds toward negative infinity. The right part is equivalent to `sum + (x % 2 == 1 || y % 2 == 1)`.assembly ("memory-safe") {
result :=add(sum, and(or(xInt, yInt), 1))
}
} else {
// Add 1 if both x and y are odd to account for the double 0.5 remainder truncated after shifting.
result = wrap(sum + (xInt & yInt &1));
}
}
}
/// @notice Yields the smallest whole number greater than or equal to x.////// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts./// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.////// Requirements:/// - x must be less than or equal to `MAX_WHOLE_SD59x18`.////// @param x The SD59x18 number to ceil./// @param result The smallest whole number greater than or equal to x, as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionceil(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt > uMAX_WHOLE_SD59x18) {
revert Errors.PRBMath_SD59x18_Ceil_Overflow(x);
}
int256 remainder = xInt % uUNIT;
if (remainder ==0) {
result = x;
} else {
unchecked {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.int256 resultInt = xInt - remainder;
if (xInt >0) {
resultInt += uUNIT;
}
result = wrap(resultInt);
}
}
}
/// @notice Divides two SD59x18 numbers, returning a new SD59x18 number.////// @dev This is an extension of {Common.mulDiv} for signed numbers, which works by computing the signs and the absolute/// values separately.////// Notes:/// - Refer to the notes in {Common.mulDiv}./// - The result is rounded toward zero.////// Requirements:/// - Refer to the requirements in {Common.mulDiv}./// - None of the inputs can be `MIN_SD59x18`./// - The denominator must not be zero./// - The result must fit in SD59x18.////// @param x The numerator as an SD59x18 number./// @param y The denominator as an SD59x18 number./// @param result The quotient as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctiondiv(SD59x18 x, SD59x18 y) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {
revert Errors.PRBMath_SD59x18_Div_InputTooSmall();
}
// Get hold of the absolute values of x and y.uint256 xAbs;
uint256 yAbs;
unchecked {
xAbs = xInt <0 ? uint256(-xInt) : uint256(xInt);
yAbs = yInt <0 ? uint256(-yInt) : uint256(yInt);
}
// Compute the absolute value (x*UNIT÷y). The resulting value must fit in SD59x18.uint256 resultAbs = Common.mulDiv(xAbs, uint256(uUNIT), yAbs);
if (resultAbs >uint256(uMAX_SD59x18)) {
revert Errors.PRBMath_SD59x18_Div_Overflow(x, y);
}
// Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for// negative, 0 for positive or zero).bool sameSign = (xInt ^ yInt) >-1;
// If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.unchecked {
result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));
}
}
/// @notice Calculates the natural exponent of x using the following formula:////// $$/// e^x = 2^{x * log_2{e}}/// $$////// @dev Notes:/// - Refer to the notes in {exp2}.////// Requirements:/// - Refer to the requirements in {exp2}./// - x must be less than 133_084258667509499441.////// @param x The exponent as an SD59x18 number./// @return result The result as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionexp(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
// This check prevents values greater than 192e18 from being passed to {exp2}.if (xInt > uEXP_MAX_INPUT) {
revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x);
}
unchecked {
// Inline the fixed-point multiplication to save gas.int256 doubleUnitProduct = xInt * uLOG2_E;
result = exp2(wrap(doubleUnitProduct / uUNIT));
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method using the following formula:////// $$/// 2^{-x} = \frac{1}{2^x}/// $$////// @dev See https://ethereum.stackexchange.com/q/79903/24693.////// Notes:/// - If x is less than -59_794705707972522261, the result is zero.////// Requirements:/// - x must be less than 192e18./// - The result must fit in SD59x18.////// @param x The exponent as an SD59x18 number./// @return result The result as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionexp2(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt <0) {
// The inverse of any number less than this is truncated to zero.if (xInt <-59_794705707972522261) {
return ZERO;
}
unchecked {
// Inline the fixed-point inversion to save gas.
result = wrap(uUNIT_SQUARED / exp2(wrap(-xInt)).unwrap());
}
} else {
// Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format.if (xInt > uEXP2_MAX_INPUT) {
revert Errors.PRBMath_SD59x18_Exp2_InputTooBig(x);
}
unchecked {
// Convert x to the 192.64-bit fixed-point format.uint256 x_192x64 =uint256((xInt <<64) / uUNIT);
// It is safe to cast the result to int256 due to the checks above.
result = wrap(int256(Common.exp2(x_192x64)));
}
}
}
/// @notice Yields the greatest whole number less than or equal to x.////// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.////// Requirements:/// - x must be greater than or equal to `MIN_WHOLE_SD59x18`.////// @param x The SD59x18 number to floor./// @param result The greatest whole number less than or equal to x, as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionfloor(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt < uMIN_WHOLE_SD59x18) {
revert Errors.PRBMath_SD59x18_Floor_Underflow(x);
}
int256 remainder = xInt % uUNIT;
if (remainder ==0) {
result = x;
} else {
unchecked {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.int256 resultInt = xInt - remainder;
if (xInt <0) {
resultInt -= uUNIT;
}
result = wrap(resultInt);
}
}
}
/// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right./// of the radix point for negative numbers./// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part/// @param x The SD59x18 number to get the fractional part of./// @param result The fractional part of x as an SD59x18 number.functionfrac(SD59x18 x) purereturns (SD59x18 result) {
result = wrap(x.unwrap() % uUNIT);
}
/// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$.////// @dev Notes:/// - The result is rounded toward zero.////// Requirements:/// - x * y must fit in SD59x18./// - x * y must not be negative, since complex numbers are not supported.////// @param x The first operand as an SD59x18 number./// @param y The second operand as an SD59x18 number./// @return result The result as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctiongm(SD59x18 x, SD59x18 y) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
if (xInt ==0|| yInt ==0) {
return ZERO;
}
unchecked {
// Equivalent to `xy / x != y`. Checking for overflow this way is faster than letting Solidity do it.int256 xyInt = xInt * yInt;
if (xyInt / xInt != yInt) {
revert Errors.PRBMath_SD59x18_Gm_Overflow(x, y);
}
// The product must not be negative, since complex numbers are not supported.if (xyInt <0) {
revert Errors.PRBMath_SD59x18_Gm_NegativeProduct(x, y);
}
// We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT`// during multiplication. See the comments in {Common.sqrt}.uint256 resultUint = Common.sqrt(uint256(xyInt));
result = wrap(int256(resultUint));
}
}
/// @notice Calculates the inverse of x.////// @dev Notes:/// - The result is rounded toward zero.////// Requirements:/// - x must not be zero.////// @param x The SD59x18 number for which to calculate the inverse./// @return result The inverse as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctioninv(SD59x18 x) purereturns (SD59x18 result) {
result = wrap(uUNIT_SQUARED / x.unwrap());
}
/// @notice Calculates the natural logarithm of x using the following formula:////// $$/// ln{x} = log_2{x} / log_2{e}/// $$////// @dev Notes:/// - Refer to the notes in {log2}./// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`.////// Requirements:/// - Refer to the requirements in {log2}.////// @param x The SD59x18 number for which to calculate the natural logarithm./// @return result The natural logarithm as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionln(SD59x18 x) purereturns (SD59x18 result) {
// Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that// {log2} can return is ~195_205294292027477728.
result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E);
}
/// @notice Calculates the common logarithm of x using the following formula:////// $$/// log_{10}{x} = log_2{x} / log_2{10}/// $$////// However, if x is an exact power of ten, a hard coded value is returned.////// @dev Notes:/// - Refer to the notes in {log2}.////// Requirements:/// - Refer to the requirements in {log2}.////// @param x The SD59x18 number for which to calculate the common logarithm./// @return result The common logarithm as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionlog10(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt <0) {
revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);
}
// Note that the `mul` in this block is the standard multiplication operation, not {SD59x18.mul}.// prettier-ignoreassembly ("memory-safe") {
switch x
case1 { result :=mul(uUNIT, sub(0, 18)) }
case10 { result :=mul(uUNIT, sub(1, 18)) }
case100 { result :=mul(uUNIT, sub(2, 18)) }
case1000 { result :=mul(uUNIT, sub(3, 18)) }
case10000 { result :=mul(uUNIT, sub(4, 18)) }
case100000 { result :=mul(uUNIT, sub(5, 18)) }
case1000000 { result :=mul(uUNIT, sub(6, 18)) }
case10000000 { result :=mul(uUNIT, sub(7, 18)) }
case100000000 { result :=mul(uUNIT, sub(8, 18)) }
case1000000000 { result :=mul(uUNIT, sub(9, 18)) }
case10000000000 { result :=mul(uUNIT, sub(10, 18)) }
case100000000000 { result :=mul(uUNIT, sub(11, 18)) }
case1000000000000 { result :=mul(uUNIT, sub(12, 18)) }
case10000000000000 { result :=mul(uUNIT, sub(13, 18)) }
case100000000000000 { result :=mul(uUNIT, sub(14, 18)) }
case1000000000000000 { result :=mul(uUNIT, sub(15, 18)) }
case10000000000000000 { result :=mul(uUNIT, sub(16, 18)) }
case100000000000000000 { result :=mul(uUNIT, sub(17, 18)) }
case1000000000000000000 { result :=0 }
case10000000000000000000 { result := uUNIT }
case100000000000000000000 { result :=mul(uUNIT, 2) }
case1000000000000000000000 { result :=mul(uUNIT, 3) }
case10000000000000000000000 { result :=mul(uUNIT, 4) }
case100000000000000000000000 { result :=mul(uUNIT, 5) }
case1000000000000000000000000 { result :=mul(uUNIT, 6) }
case10000000000000000000000000 { result :=mul(uUNIT, 7) }
case100000000000000000000000000 { result :=mul(uUNIT, 8) }
case1000000000000000000000000000 { result :=mul(uUNIT, 9) }
case10000000000000000000000000000 { result :=mul(uUNIT, 10) }
case100000000000000000000000000000 { result :=mul(uUNIT, 11) }
case1000000000000000000000000000000 { result :=mul(uUNIT, 12) }
case10000000000000000000000000000000 { result :=mul(uUNIT, 13) }
case100000000000000000000000000000000 { result :=mul(uUNIT, 14) }
case1000000000000000000000000000000000 { result :=mul(uUNIT, 15) }
case10000000000000000000000000000000000 { result :=mul(uUNIT, 16) }
case100000000000000000000000000000000000 { result :=mul(uUNIT, 17) }
case1000000000000000000000000000000000000 { result :=mul(uUNIT, 18) }
case10000000000000000000000000000000000000 { result :=mul(uUNIT, 19) }
case100000000000000000000000000000000000000 { result :=mul(uUNIT, 20) }
case1000000000000000000000000000000000000000 { result :=mul(uUNIT, 21) }
case10000000000000000000000000000000000000000 { result :=mul(uUNIT, 22) }
case100000000000000000000000000000000000000000 { result :=mul(uUNIT, 23) }
case1000000000000000000000000000000000000000000 { result :=mul(uUNIT, 24) }
case10000000000000000000000000000000000000000000 { result :=mul(uUNIT, 25) }
case100000000000000000000000000000000000000000000 { result :=mul(uUNIT, 26) }
case1000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 27) }
case10000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 28) }
case100000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 29) }
case1000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 30) }
case10000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 31) }
case100000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 32) }
case1000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 33) }
case10000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 34) }
case100000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 35) }
case1000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 36) }
case10000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 37) }
case100000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 38) }
case1000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 39) }
case10000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 40) }
case100000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 41) }
case1000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 42) }
case10000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 43) }
case100000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 44) }
case1000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 45) }
case10000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 46) }
case100000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 47) }
case1000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 48) }
case10000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 49) }
case100000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 50) }
case1000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 51) }
case10000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 52) }
case100000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 53) }
case1000000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 54) }
case10000000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 55) }
case100000000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 56) }
case1000000000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 57) }
case10000000000000000000000000000000000000000000000000000000000000000000000000000 { result :=mul(uUNIT, 58) }
default { result := uMAX_SD59x18 }
}
if (result.unwrap() == uMAX_SD59x18) {
unchecked {
// Inline the fixed-point division to save gas.
result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10);
}
}
}
/// @notice Calculates the binary logarithm of x using the iterative approximation algorithm:////// $$/// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2)/// $$////// For $0 \leq x \lt 1$, the input is inverted:////// $$/// log_2{x} = -log_2{\frac{1}{x}}/// $$////// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation.////// Notes:/// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal.////// Requirements:/// - x must be greater than zero.////// @param x The SD59x18 number for which to calculate the binary logarithm./// @return result The binary logarithm as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionlog2(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt <=0) {
revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x);
}
unchecked {
int256 sign;
if (xInt >= uUNIT) {
sign =1;
} else {
sign =-1;
// Inline the fixed-point inversion to save gas.
xInt = uUNIT_SQUARED / xInt;
}
// Calculate the integer part of the logarithm.uint256 n = Common.msb(uint256(xInt / uUNIT));
// This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow// because n is at most 255, `UNIT` is 1e18, and the sign is either 1 or -1.int256 resultInt =int256(n) * uUNIT;
// Calculate $y = x * 2^{-n}$.int256 y = xInt >> n;
// If y is the unit number, the fractional part is zero.if (y == uUNIT) {
return wrap(resultInt * sign);
}
// Calculate the fractional part via the iterative approximation.// The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient.int256 DOUBLE_UNIT =2e18;
for (int256 delta = uHALF_UNIT; delta >0; delta >>=1) {
y = (y * y) / uUNIT;
// Is y^2 >= 2e18 and so in the range [2e18, 4e18)?if (y >= DOUBLE_UNIT) {
// Add the 2^{-m} factor to the logarithm.
resultInt = resultInt + delta;
// Halve y, which corresponds to z/2 in the Wikipedia article.
y >>=1;
}
}
resultInt *= sign;
result = wrap(resultInt);
}
}
/// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number.////// @dev Notes:/// - Refer to the notes in {Common.mulDiv18}.////// Requirements:/// - Refer to the requirements in {Common.mulDiv18}./// - None of the inputs can be `MIN_SD59x18`./// - The result must fit in SD59x18.////// @param x The multiplicand as an SD59x18 number./// @param y The multiplier as an SD59x18 number./// @return result The product as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionmul(SD59x18 x, SD59x18 y) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {
revert Errors.PRBMath_SD59x18_Mul_InputTooSmall();
}
// Get hold of the absolute values of x and y.uint256 xAbs;
uint256 yAbs;
unchecked {
xAbs = xInt <0 ? uint256(-xInt) : uint256(xInt);
yAbs = yInt <0 ? uint256(-yInt) : uint256(yInt);
}
// Compute the absolute value (x*y÷UNIT). The resulting value must fit in SD59x18.uint256 resultAbs = Common.mulDiv18(xAbs, yAbs);
if (resultAbs >uint256(uMAX_SD59x18)) {
revert Errors.PRBMath_SD59x18_Mul_Overflow(x, y);
}
// Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for// negative, 0 for positive or zero).bool sameSign = (xInt ^ yInt) >-1;
// If the inputs have the same sign, the result should be positive. Otherwise, it should be negative.unchecked {
result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));
}
}
/// @notice Raises x to the power of y using the following formula:////// $$/// x^y = 2^{log_2{x} * y}/// $$////// @dev Notes:/// - Refer to the notes in {exp2}, {log2}, and {mul}./// - Returns `UNIT` for 0^0.////// Requirements:/// - Refer to the requirements in {exp2}, {log2}, and {mul}.////// @param x The base as an SD59x18 number./// @param y Exponent to raise x to, as an SD59x18 number/// @return result x raised to power y, as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionpow(SD59x18 x, SD59x18 y) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
int256 yInt = y.unwrap();
// If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero.if (xInt ==0) {
return yInt ==0 ? UNIT : ZERO;
}
// If x is `UNIT`, the result is always `UNIT`.elseif (xInt == uUNIT) {
return UNIT;
}
// If y is zero, the result is always `UNIT`.if (yInt ==0) {
return UNIT;
}
// If y is `UNIT`, the result is always x.elseif (yInt == uUNIT) {
return x;
}
// Calculate the result using the formula.
result = exp2(mul(log2(x), y));
}
/// @notice Raises x (an SD59x18 number) to the power y (an unsigned basic integer) using the well-known/// algorithm "exponentiation by squaring".////// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring.////// Notes:/// - Refer to the notes in {Common.mulDiv18}./// - Returns `UNIT` for 0^0.////// Requirements:/// - Refer to the requirements in {abs} and {Common.mulDiv18}./// - The result must fit in SD59x18.////// @param x The base as an SD59x18 number./// @param y The exponent as a uint256./// @return result The result as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionpowu(SD59x18 x, uint256 y) purereturns (SD59x18 result) {
uint256 xAbs =uint256(abs(x).unwrap());
// Calculate the first iteration of the loop in advance.uint256 resultAbs = y &1>0 ? xAbs : uint256(uUNIT);
// Equivalent to `for(y /= 2; y > 0; y /= 2)`.uint256 yAux = y;
for (yAux >>=1; yAux >0; yAux >>=1) {
xAbs = Common.mulDiv18(xAbs, xAbs);
// Equivalent to `y % 2 == 1`.if (yAux &1>0) {
resultAbs = Common.mulDiv18(resultAbs, xAbs);
}
}
// The result must fit in SD59x18.if (resultAbs >uint256(uMAX_SD59x18)) {
revert Errors.PRBMath_SD59x18_Powu_Overflow(x, y);
}
unchecked {
// Is the base negative and the exponent odd? If yes, the result should be negative.int256 resultInt =int256(resultAbs);
bool isNegative = x.unwrap() <0&& y &1==1;
if (isNegative) {
resultInt =-resultInt;
}
result = wrap(resultInt);
}
}
/// @notice Calculates the square root of x using the Babylonian method.////// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.////// Notes:/// - Only the positive root is returned./// - The result is rounded toward zero.////// Requirements:/// - x cannot be negative, since complex numbers are not supported./// - x must be less than `MAX_SD59x18 / UNIT`.////// @param x The SD59x18 number for which to calculate the square root./// @return result The result as an SD59x18 number./// @custom:smtchecker abstract-function-nondetfunctionsqrt(SD59x18 x) purereturns (SD59x18 result) {
int256 xInt = x.unwrap();
if (xInt <0) {
revert Errors.PRBMath_SD59x18_Sqrt_NegativeInput(x);
}
if (xInt > uMAX_SD59x18 / uUNIT) {
revert Errors.PRBMath_SD59x18_Sqrt_Overflow(x);
}
unchecked {
// Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two SD59x18 numbers.// In this case, the two numbers are both the square root.uint256 resultUint = Common.sqrt(uint256(xInt * uUNIT));
result = wrap(int256(resultUint));
}
}
Contract Source Code
File 16 of 19: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)pragmasolidity ^0.8.0;import"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.8.19;import"./Casting.sol"asCasting;
import"./Helpers.sol"asHelpers;
import"./Math.sol"asMath;
/// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18/// decimals. The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256./// @dev The value type is defined here so it can be imported in all other files.type UD60x18 isuint256;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/using {
Casting.intoSD1x18,
Casting.intoUD2x18,
Casting.intoSD59x18,
Casting.intoUint128,
Casting.intoUint256,
Casting.intoUint40,
Casting.unwrap
} forUD60x18global;
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/// The global "using for" directive makes the functions in this library callable on the UD60x18 type.using {
Math.avg,
Math.ceil,
Math.div,
Math.exp,
Math.exp2,
Math.floor,
Math.frac,
Math.gm,
Math.inv,
Math.ln,
Math.log10,
Math.log2,
Math.mul,
Math.pow,
Math.powu,
Math.sqrt
} forUD60x18global;
/*//////////////////////////////////////////////////////////////////////////
HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/// The global "using for" directive makes the functions in this library callable on the UD60x18 type.using {
Helpers.add,
Helpers.and,
Helpers.eq,
Helpers.gt,
Helpers.gte,
Helpers.isZero,
Helpers.lshift,
Helpers.lt,
Helpers.lte,
Helpers.mod,
Helpers.neq,
Helpers.not,
Helpers.or,
Helpers.rshift,
Helpers.sub,
Helpers.uncheckedAdd,
Helpers.uncheckedSub,
Helpers.xor
} forUD60x18global;
/*//////////////////////////////////////////////////////////////////////////
OPERATORS
//////////////////////////////////////////////////////////////////////////*/// The global "using for" directive makes it possible to use these operators on the UD60x18 type.using {
Helpers.addas+,
Helpers.and2as&,
Math.divas/,
Helpers.eqas==,
Helpers.gtas>,
Helpers.gteas>=,
Helpers.ltas<,
Helpers.lteas<=,
Helpers.oras|,
Helpers.modas%,
Math.mulas*,
Helpers.neqas!=,
Helpers.notas~,
Helpers.subas-,
Helpers.xoras^
} forUD60x18global;