{"repo":"PaulRBerg/prb-math","free":true,"listed":false,"github":"https://github.com/PaulRBerg/prb-math","clone":"git clone https://github.com/PaulRBerg/prb-math.git","description":"Solidity library for advanced fixed-point math","language":"Solidity","stars":1007,"topics":["decentralized-finance","defi","ethereum","evm","library","math","smart-contracts","solidity"],"license":"MIT","category":"dev_tool","readme_excerpt":"# PRBMath [![GitHub Actions][gha-badge]][gha] [![Foundry][foundry-badge]][foundry] [![License: MIT][license-badge]][license]\n\n[gha]: https://github.com/PaulRBerg/prb-math/actions\n[gha-badge]: https://github.com/PaulRBerg/prb-math/actions/workflows/ci.yml/badge.svg\n[foundry]: https://getfoundry.sh/\n[foundry-badge]: https://img.shields.io/badge/Built%20with-Foundry-FFDB1C.svg\n[license]: https://opensource.org/licenses/MIT\n[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg\n\n<div align=\"center\">\n  <img src=\"./assets/logo.png\" alt=\"PRBMath Logo\" width=\"250\">\n</div>\n\n**Solidity library for advanced fixed-point math** that operates with signed 59.18-decimal fixed-point and unsigned 60.18-decimal fixed-point numbers.\nThe name of the number format comes from the integer part having up to 59 digits for signed numbers and 60 digits for unsigned numbers, while the\nfractional part has up to 18 decimals. The numbers are bound by the minimum and the maximum values permitted by the Solidity types int256 and uint256.\n\n- Operates with signed and unsigned denary fixed-point numbers, with 18 trailing decimals\n- Offers advanced math functions like logarithms, exponentials, powers and square roots\n- Provides type safety via user-defined value types\n- Gas efficient, but still user-friendly\n- Ergonomic developer experience thanks to using free functions instead of libraries\n- Bakes in overflow-safe multiplication and division via `mulDiv`\n- Reverts with custom errors instead of reason strings\n- Well-documented with NatSpec comments\n- Built and tested with Foundry\n\n> [!NOTE]\n>\n> PRBMath is a fixed-point math library that is at the same time intuitive, efficient and safe.\n> [ABDKMath64x64](https://github.com/abdk-consulting/abdk-libraries-solidity) is fast, but uses binary numbers, which are counter-intuitive.\n> [Solmate](https://github.com/transmissions11/solmate) is fast and intuitive, but lacks type safety.\n\n## 📦 Install\n\n### 🟢 Node.js\n\nThis is the recommended approach.\n\nInstall PRBMath using your favorite package manager, e.g., with Bun:\n\n```shell\nbun add @prb/math\n```\n\nThen, if you are using Foundry, you need to add this to your `remappings.txt` file:\n\n```text\n@prb/math/=node_modules/@prb/math/\n```\n\n### 🔗 Git Submodules\n\nThis installation method is not recommended, but it is available for those who prefer it.\n\nFirst, install the submodule using Forge:\n\n```shell\nforge install PaulRBerg/prb-math@release-v4\n```\n\nYour `.gitmodules` file should now contain the following entry:\n\n```toml\n[submodule \"lib/prb-math\"]\n  branch = \"release-v4\"\n  path = \"lib/prb-math\"\n  url = \"https://github.com/PaulRBerg/prb-math\"\n```\n\nFinally, add this to your `remappings.txt` file:\n\n```text\n@prb/math/=lib/prb-math/\n```\n\n## 🚀 Usage\n\nThere are two user-defined value types:\n\n1. SD59x18 (signed)\n2. UD60x18 (unsigned)\n\nIf you don't know what a user-defined value type is, check out this [blog post](https://blog.soliditylang.org/2021/09/27/user-defined-value-types/).\n\nIf you don't need negative numbers, there's no point in using the signed flavor `SD59x18`. The unsigned flavor `UD60x18` is more gas efficient.\n\nNote that PRBMath is not a library in the Solidity [sense](https://docs.soliditylang.org/en/v0.8.17/contracts.html#libraries). It's just a collection\nof free functions.\n\n### 📥 Importing\n\nIt is recommended that you import PRBMath using specific symbols. Importing full files can result in Solidity complaining about duplicate definitions\nand static analyzers like Slither erroring, especially as repos grow and have more dependencies with overlapping names.\n\n```solidity\npragma solidity >=0.8.19;\n\nimport { SD59x18 } from \"@prb/math/src/SD59x18.sol\";\nimport { UD60x18 } from \"@prb/math/src/UD60x18.sol\";\n```\n\nAny function that is not available in the types directly has to be imported explicitly. Here's an example for the `sd` and the `ud` functions:\n\n```solidity\npragma solidity >=0.8.19;\n\nimport { SD59x18, sd } from \"@prb/math/src/SD59x18.sol\";\nimport { UD60x18, ud } from \"@prb/math/src/UD60x18.sol\";\n```\n\nNote that PRBMath can only be used in Solidity v0.8.19 and above.\n\n### ➕ SD59x18\n\n```solidity\n// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.19;\n\nimport { SD59x18, sd } from \"@prb/math/src/SD59x18.sol\";\n\ncontract SignedConsumer {\n  /// @notice Calculates 5% of the given signed number.\n  /// @dev Try this with x = 400e18.\n  function signedPercentage(SD59x18 x) external pure returns (SD59x18 result) {\n    SD59x18 fivePercent = sd(0.05e18);\n    result = x.mul(fivePercent);\n  }\n\n  /// @notice Calculates the binary logarithm of the given signed number.\n  /// @dev Try this with x = 128e18.\n  function signedLog2(SD59x18 x) external pure returns (SD59x18 result) {\n    result = x.log2();\n  }\n}\n```\n\n### ➕ UD60x18\n\n```solidity\n// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.19;\n\nimport { UD60x18, ud } from \"@prb/math/src/UD60x18.sol\";\n\ncontract UnsignedConsumer {\n  /// @notice Calculates 5% of the given unsigned number.\n  /// @dev Try this with x = 400e18.\n  function unsignedPercentage(UD60x18 x) external pure returns (UD60x18 result) {\n    UD60x18 fivePercent = ud(0.05e18);\n    result = x.mul(fivePercent);\n  }\n\n  /// @notice Calculates the binary logarithm of the given unsigned number.\n  /// @dev Try this with x = 128e18.\n  function unsignedLog2(UD60x18 x) external pure returns (UD60x18 result) {\n    result = x.log2();\n  }\n}\n```\n\n## ✨ Features\n\nBecause there's significant overlap between the features available in SD59x18 and UD60x18, there is only one table per section. If in doubt, refer to\nthe source code, which is well-documented with NatSpec comments.\n\n### 🔢 Mathematical Functions\n\n| Name    | Operator | Description                                      |\n| ------- | -------- | ------------------------------------------------ |\n| `abs`   | N/A      | Absolute value                                   |\n| `avg`   | N/A      | Arithmetic average                               |\n| `ceil`  | N/A      | Smallest whole number greater than or equal to x |\n| `div`   | `/`      | Fixed-point division                             |\n| `exp`   | N/A      | Natural exponential e^x                          |\n| `exp2`  | N/A      | Binary exponential 2^x                           |\n| `floor` | N/A      | Greatest whole number less than or equal to x    |\n| `frac`  | N/A      | Fractional part                                  |\n| `gm`    | N/A      | Geometric mean                                   |\n| `inv`   | N/A      | Inverse 1÷x                                      |\n| `ln`    | N/A      | Natural logarithm ln(x)                          |\n| `log10` | N/A      | Common logarithm log10(x)                        |\n| `log2`  | N/A      | Binary logarithm log2(x)                         |\n| `mul`   | `*`      | Fixed-point multiplication                       |\n| `pow`   | N/A      | Power function x^y                               |\n| `powu`  | N/A      | Power function x^y with y simple integer         |\n| `sign`  | N/A      | Sign of the number                               |\n| `sqrt`  | N/A      | Square root                                      |\n\n### 🔗 Adjacent Value Types\n\nPRBMath provides adjacent value types that serve as abstractions over other vanilla types:\n\n| Value Type | Underlying Type |\n| ---------- | --------------- |\n| `SD1x18`   | int64           |\n| `SD21x18`  | int128          |\n| `UD2x18`   | uint64          |\n| `UD21x18`  | uint128         |\n\nThese are useful if you want to save gas by using a lower bit width integer, e.g., in a struct.\n\nNote that these types don't have any mathematical functionality. To do math with them, you will have to unwrap them into a simple integer and then\ncast to the core types `SD59x18` and `UD60x18`.\n\n### 🔄 Casting Functions\n\nAll PRBMath types have casting functions to and from all other types, including a few basic types like `uint128` and `uint40`.\n\n| Name          | Description               |\n| ------------- | ------------------------- |\n| `intoInt256`  | Casts a number to int256  |\n| `intoSD1x18`  | Casts a number to SD1x18  |\n| `intoSD21x18` | Casts a number to SD21x18 |\n| `intoSD59x18` | Casts a number to SD59x18 |\n| `intoUD2x18`  | Casts a number to UD2x18  |\n| `intoUD21x18` | Casts a number to UD21x18 |\n| `intoUD60x18` | Casts a number to UD60x18 |\n| `intoUint256` | Casts a number to uint256 |\n| `intoUint128` | Casts a number to uint128 |\n| `intoUint40`  | Casts a number to uint40  |\n| `sd1x18`      | Alias for `SD1x18.wrap`   |\n| `sd21x18`     | Alias for `SD21x18.wrap`  |\n| `sd59x18`     | Alias for `SD59x18.wrap`  |\n| `ud2x18`      | Alias for `UD2x18.wrap`   |\n| `ud21x18`     | Alias for `UD21x18.wrap`  |\n| `ud60x18`     | Alias for `UD60x18.wrap`  |\n\n### ⚡ Conversion Functions\n\nThe difference between \"conversion\" and \"casting\" is that conversion functions multiply or divide the inputs, whereas casting functions simply cast\nthem.\n\n| Name               | Description                                                           |\n| ------------------ | --------------------------------------------------------------------- |\n| `convert(SD59x18)` | Converts an SD59x18 number to a simple integer by dividing it by 1e18 |\n| `convert(UD60x18)` | Converts a UD60x18 number to a simple integer by dividing it by 1e18  |\n| `convert(int256)`  | Converts a simple integer to SD59x18 by multiplying it by 1e18        |\n| `convert(uint256)` | Converts a simple integer to UD60x18 type by multiplying it by 1e18   |\n\n### 🛠️ Helper Functions\n\nIn addition to offering mathematical, casting, and conversion functions, PRBMath provides numerous helper functions for user-defined value types:\n\n| Name           | Operator | Description               |\n| -------------- | -------- | ------------------------- |\n| `add`          | `+`      | Checked addition          |\n| `and`          | `&`      | Bitwise AND               |\n| `eq`           | `==`     | Equality                  |\n| `gt`           | `>`      | Greater tha","default_branch":"main","files":164,"tree":[".editorconfig",".github/FUNDING.yml",".github/ISSUE_TEMPLATE/1-bug-report.yml",".github/ISSUE_TEMPLATE/2-feature-request.yml",".github/ISSUE_TEMPLATE/config.yml",".github/workflows/ci-multibuild.yml",".github/workflows/ci.yml",".github/workflows/release.yml",".gitignore",".prettierignore",".prettierrc.yml",".serena/project.yml",".solhint.json",".vscode/settings.json","AGENTS.md","CHANGELOG.md","CLAUDE.md","LICENSE.md","README.md","SECURITY.md","assets/logo.png","assets/op.png","bun.lock","foundry.toml","funding.json","justfile","package.json","src/Common.sol","src/SD1x18.sol","src/SD21x18.sol","src/SD59x18.sol","src/UD21x18.sol","src/UD2x18.sol","src/UD60x18.sol","src/casting/Uint128.sol","src/casting/Uint256.sol","src/casting/Uint40.sol","src/sd1x18/Casting.sol","src/sd1x18/Constants.sol","src/sd1x18/Errors.sol","src/sd1x18/ValueType.sol","src/sd21x18/Casting.sol","src/sd21x18/Constants.sol","src/sd21x18/Errors.sol","src/sd21x18/ValueType.sol","src/sd59x18/Casting.sol","src/sd59x18/Constants.sol","src/sd59x18/Conversions.sol","src/sd59x18/Errors.sol","src/sd59x18/Helpers.sol","src/sd59x18/Math.sol","src/sd59x18/ValueType.sol","src/ud21x18/Casting.sol","src/ud21x18/Constants.sol","src/ud21x18/Errors.sol","src/ud21x18/ValueType.sol","src/ud2x18/Casting.sol","src/ud2x18/Constants.sol","src/ud2x18/Errors.sol","src/ud2x18/ValueType.sol","src/ud60x18/Casting.sol","src/ud60x18/Constants.sol","src/ud60x18/Conversions.sol","src/ud60x18/Errors.sol","src/ud60x18/Helpers.sol","src/ud60x18/Math.sol","src/ud60x18/ValueType.sol","test/.solhint.json","test/Base.t.sol","test/fuzz/casting/Uint128.t.sol","test/fuzz/casting/Uint256.t.sol","test/fuzz/casting/Uint40.t.sol","test/fuzz/common/msb.t.sol","test/fuzz/common/sqrt.t.sol","test/fuzz/sd1x18/casting/Casting.t.sol","test/fuzz/sd21x18/casting/Casting.t.sol","test/fuzz/sd59x18/casting/Casting.t.sol","test/fuzz/sd59x18/helpers/Helpers.t.sol","test/fuzz/sd59x18/math/pow/pow.t.sol","test/fuzz/ud21x18/casting/Casting.t.sol","test/fuzz/ud2x18/casting/Casting.t.sol","test/fuzz/ud60x18/casting/Casting.t.sol","test/fuzz/ud60x18/helpers/Helpers.t.sol","test/fuzz/ud60x18/math/pow/pow.t.sol","test/unit/sd59x18/SD59x18.t.sol","test/unit/sd59x18/conversion/convert-from/convertFrom.t.sol","test/unit/sd59x18/conversion/convert-from/convertFrom.tree","test/unit/sd59x18/conversion/convert-to/convertTo.t.sol","test/unit/sd59x18/conversion/convert-to/convertTo.tree","test/unit/sd59x18/math/abs/abs.t.sol","test/unit/sd59x18/math/abs/abs.tree","test/unit/sd59x18/math/avg/avg.t.sol","test/unit/sd59x18/math/avg/avg.tree","test/unit/sd59x18/math/ceil/ceil.t.sol","test/unit/sd59x18/math/ceil/ceil.tree","test/unit/sd59x18/math/div/div.t.sol","test/unit/sd59x18/math/div/div.tree","test/unit/sd59x18/math/exp/exp.t.sol","test/unit/sd59x18/math/exp/exp.tree","test/unit/sd59x18/math/exp2/exp2.t.sol","test/unit/sd59x18/math/exp2/exp2.tree","test/unit/sd59x18/math/floor/floor.t.sol","test/unit/sd59x18/math/floor/floor.tree","test/unit/sd59x18/math/frac/frac.t.sol","test/unit/sd59x18/math/frac/frac.tree","test/unit/sd59x18/math/gm/gm.t.sol","test/unit/sd59x18/math/gm/gm.tree","test/unit/sd59x18/math/inv/inv.t.sol","test/unit/sd59x18/math/inv/inv.tree","test/unit/sd59x18/math/ln/ln.t.sol","test/unit/sd59x18/math/ln/ln.tree","test/unit/sd59x18/math/log10/log10.t.sol","test/unit/sd59x18/math/log10/log10.tree","test/unit/sd59x18/math/log2/log2.t.sol","test/unit/sd59x18/math/log2/log2.tree","test/unit/sd59x18/math/mul/mul.t.sol","test/unit/sd59x18/math/mul/mul.tree","test/unit/sd59x18/math/pow/pow.t.sol","test/unit/sd59x18/math/pow/pow.tree","test/unit/sd59x18/math/powu/powu.t.sol","test/unit/sd59x18/math/powu/powu.tree","test/unit/sd59x18/math/sign/sign.t.sol","test/unit/sd59x18/math/sign/sign.tree","test/unit/sd59x18/math/sqrt/sqrt.t.sol","test/unit/sd59x18/math/sqrt/sqrt.tree","test/unit/ud60x18/UD60x18.t.sol","test/unit/ud60x18/conversion/convert-from/convertFrom.t.sol","test/unit/ud60x18/conversion/convert-from/convertFrom.tree","test/unit/ud60x18/conversion/convert-to/convertTo.t.sol","test/unit/ud60x18/conversion/convert-to/convertTo.tree","test/unit/ud60x18/math/avg/avg.t.sol","test/unit/ud60x18/math/avg/avg.tree","test/unit/ud60x18/math/ceil/ceil.t.sol","test/unit/ud60x18/math/ceil/ceil.tree","test/unit/ud60x18/math/div/div.t.sol","test/unit/ud60x18/math/div/div.tree","test/unit/ud60x18/math/exp/exp.t.sol","test/unit/ud60x18/math/exp/exp.tree","test/unit/ud60x18/math/exp2/exp2.t.sol","test/unit/ud60x18/math/exp2/exp2.tree","test/unit/ud60x18/math/floor/floor.t.sol","test/unit/ud60x18/math/floor/floor.tree","test/unit/ud60x18/math/frac/frac.t.sol","test/unit/ud60x18/math/frac/frac.tree","test/unit/ud60x18/math/gm/gm.t.sol","test/unit/ud60x18/math/gm/gm.tree","test/unit/ud60x18/math/inv/inv.t.sol","test/unit/ud60x18/math/inv/inv.tree","test/unit/ud60x18/math/ln/ln.t.sol","test/unit/ud60x18/math/ln/ln.tree","test/unit/ud60x18/math/log10/log10.t.sol","test/unit/ud60x18/math/log10/log10.tree","test/unit/ud60x18/math/log2/log2.t.sol","test/unit/ud60x18/math/log2/log2.tree","test/unit/ud60x18/math/mul/mul.t.sol","test/unit/ud60x18/math/mul/mul.tree","test/unit/ud60x18/math/pow/pow.t.sol","test/unit/ud60x18/math/pow/pow.tree","test/unit/ud60x18/math/powu/powu.t.sol","test/unit/ud60x18/math/powu/powu.tree","test/unit/ud60x18/math/sqrt/sqrt.t.sol","test/unit/ud60x18/math/sqrt/sqrt.tree","test/utils/Assertions.sol","test/utils/Utils.sol"],"storefront":"/r/PaulRBerg","claimed":false,"request_supported":{"post":"https://gitbuyer.com/r/PaulRBerg/prb-math/request-supported","requests":0},"note":"indexed from public GitHub; nothing is for sale on this page. Clone it from GitHub. Paid listings live at /search."}