// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.13; library Math { // Taken from https://github.com/usmfum/USM/blob/master/src/WadMath.sol /// @dev Multiply an amount by a fixed point factor with 18 decimals, rounds down. function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x * y; unchecked { z /= 1e18; } } // Taken from https://github.com/usmfum/USM/blob/master/src/WadMath.sol /// @dev Multiply x and y, with y being fixed point. If both are integers, the result is a fixed point factor. Rounds up. function wmulup(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x * y + 1e18 - 1; // Rounds up. So (again imagining 2 decimal places): unchecked { z /= 1e18; } // 383 (3.83) * 235 (2.35) -> 90005 (9.0005), + 99 (0.0099) -> 90104, / 100 -> 901 (9.01). } // Taken from https://github.com/usmfum/USM/blob/master/src/WadMath.sol /// @dev Divide an amount by a fixed point factor with 18 decimals function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { z = (x * 1e18) / y; } // Taken from https://github.com/usmfum/USM/blob/master/src/WadMath.sol /// @dev Divide x and y, with y being fixed point. If both are integers, the result is a fixed point factor. Rounds up. function wdivup(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x * 1e18 + y; // 101 (1.01) / 1000 (10) -> (101 * 100 + 1000 - 1) / 1000 -> 11 (0.11 = 0.101 rounded up). unchecked { z -= 1; } // Can do unchecked subtraction since division in next line will catch y = 0 case anyway z /= y; } // Taken from https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol /// @dev $x ^ $n; $x is 18-decimals fixed point number function wpow(uint256 x, uint256 n) internal pure returns (uint256 z) { uint256 baseUnit = 1e18; assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := baseUnit } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store baseUnit in z for now. z := baseUnit } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, baseUnit) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, baseUnit) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, baseUnit) } } } } } /// @dev Divide an amount by a fixed point factor with 27 decimals function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { z = (x * 1e27) / y; } }