PRBMath Documentation

repository·main·Indexed 21 days ago

https://github.com/paulrberg/prb-math

A Solidity library for advanced fixed-point math using signed 59.18-decimal (SD59x18) and unsigned 60.18-decimal (UD60x18) formats. It provides high-precision, gas-efficient, and type-safe operations including logarithms, exponentials, and square roots. Requires Solidity v0.8.19 or higher.

Tokens
4.3K
Snippets
11
Records
13
Agent score
27%

What's inside PRBMath

  1. Adjacent Value Types (Gas-efficient Abstractions)

    main

    PRBMath provides adjacent value types that act as abstractions over lower bit-width integers. These are useful for saving gas when used in structs. Note that these types do not have mathematical functionality; you must unwrap them to a simple integer and then cast them to SD59x18 or UD60x18 to perform math.

    | Value Type | Underlying Type |
    | ---------- | --------------- |
    | `SD1x18`   | int64           |
    | `SD21x18`  | int128          |
    | `UD2x18`   | uint64          |
    | `UD21x18`  | uint128         |
  2. Compare Gas Efficiency of PRBMath vs ABDKMath

    main

    PRBMath's performance relative to ABDKMath depends on the specific mathematical function used.

    When to use PRBMath for efficiency: PRBMath is faster than ABDKMath for the following functions:

    • abs
    • exp
    • exp2
    • gm
    • inv
    • ln
    • log2

    When ABDKMath might be more efficient: ABDKMath is faster for:

    • avg
    • div
    • mul
    • powu
    • sqrt

    Technical Note on Performance: PRBMath's mul and div functions are generally slower than ABDKMath's because PRBMath operates with 256-bit word sizes to account for potential intermediary overflows, whereas ABDKMath operates with 128-bit word sizes.

  3. Importing PRBMath types and functions

    main

    PRBMath is a collection of free functions rather than a standard Solidity library. It is highly recommended to import specific symbols rather than entire files to avoid duplicate definition errors and issues with static analyzers like Slither. Note that PRBMath requires Solidity v0.8.19 or higher.

    pragma solidity >=0.8.19;
    
    // Recommended: Import specific symbols
    import { SD59x18 } from "@prb/math/src/SD59x18.sol";
    import { UD60x18 } from "@prb/math/src/UD60x18.sol";
    
    // To use helper functions like 'sd' or 'ud', import them explicitly
    import { SD59x18, sd } from "@prb/math/src/SD59x18.sol";
    import { UD60x18, ud } from "@prb/math/src/UD60x18.sol";
  4. Install PRBMath via Node.js (Recommended)

    main

    Install PRBMath using your preferred package manager. If you are using Foundry, you must update your remappings.txt file to include the package path.

    # Install with Bun
    bun add @prb/math

    Add to remappings.txt

    @prb/math/=node_modules/@prb/math/

  5. Using PRBMath Assertions for Testing

    main

    PRBMath includes typed assertions designed for use with PRBTest. You can inherit from Assertions to perform equality checks and other assertions directly on SD59x18 or UD60x18 types.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity >=0.8.19;
    
    import { UD60x18, ud } from "@prb/math/src/UD60x18.sol";
    import { Assertions as PRBMathAssertions } from "@prb/math/test/Assertions.sol";
    import { PRBTest } from "@prb/math/src/test/PRBTest.sol";
    
    contract MyTest is PRBTest, PRBMathAssertions {
      function testAdd() external {
        UD60x18 x = ud(1e18);
        UD60x18 y = ud(2e18);
        UD60x18 z = ud(3e18);
        assertEq(x.add(y), z);
      }
    }
  6. Set up the PRBMath development environment

    main

    To contribute to PRBMath, you need to clone the repository with its submodules and install the Node.js dependencies using bun.

    Prerequisites:

    • Git
    • Foundry
    • Node.js
    • Bun
    • Familiarity with Solidity

    Steps:

    1. Clone the repository including submodules:
      git clone --recurse-submodules -j8 git@github.com:PaulRBerg/prb-math.git
    2. Navigate to the project directory and install dependencies:
      bun install
    $ git clone --recurse-submodules -j8 git@github.com:PaulRBerg/prb-math.git
    $ bun install
  7. Install PRBMath via Git Submodules

    main

    Use this method if you prefer Git submodules over Node.js package managers. Use Forge to install the specific release branch and update your remappings.txt.

    # Install the submodule using Forge
    forge install  PaulRBerg/prb-math@release-v4

    Add to remappings.txt

    @prb/math/=lib/prb-math/

  8. Use UD60x18 (Unsigned Fixed-Point)

    main

    The UD60x18 type is used for unsigned fixed-point numbers with 18 decimal places. It is more gas-efficient than SD59x18 if negative numbers are not required. Use the ud() function to wrap values.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity >=0.8.19;
    
    import { UD60x18, ud } from "@prb/math/src/UD60x18.sol";
    
    contract UnsignedConsumer {
      /// @notice Calculates 5% of the given unsigned number.
      function unsignedPercentage(UD60x18 x) external pure returns (UD60x18 result) {
        UD60x18 fivePercent = ud(0.05e18);
        result = x.mul(fivePercent);
      }
    
      /// @notice Calculates the binary logarithm of the given unsigned number.
      function unsignedLog2(UD60x18 x) external pure returns (UD60x18 result) {
        result = x.log2();
      }
    }
  9. Use SD59x18 (Signed Fixed-Point)

    main

    The SD59x18 type is used for signed fixed-point numbers with 18 decimal places. It uses the sd() function to wrap values. It supports advanced mathematical operations like mul, log2, etc.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity >=0.8.19;
    
    import { SD59x18, sd } from "@prb/math/src/SD59x18.sol";
    
    contract SignedConsumer {
      /// @notice Calculates 5% of the given signed number.
      function signedPercentage(SD59x18 x) external pure returns (SD59x18 result) {
        SD59x18 fivePercent = sd(0.05e18);
        result = x.mul(fivePercent);
      }
    
      /// @notice Calculates the binary logarithm of the given signed number.
      function signedLog2(SD59x18 x) external pure returns (SD59x18 result) {
        result = x.log2();
      }
    }
  10. Casting and Conversion Functions Reference

    main

    PRBMath distinguishes between Casting (changing the type without changing the value) and Conversion (changing the value, e.g., by multiplying/dividing by 1e18).

    ### Casting Functions
    
    | Name          | Description               |
    | ------------- | ------------------------- |
    | `intoSD1x18`  | Casts a number to SD1x18  |
    | `intoSD59x18` | Casts a number to SD59x18 |
    | `intoUD2x18`  | Casts a number to UD2x18  |
    | `intoUD60x18` | Casts a number to UD60x18 |
    | `intoUint256` | Casts a number to uint256 |
    | `intoUint128` | Casts a number to uint128 |
    | `intoUint40`  | Casts a number to uint40  |
    | `sd1x18`      | Alias for `SD1x18.wrap`   |
    | `sd59x18`     | Alias for `SD59x18.wrap`  |
    | `ud2x18`      | Alias for `UD2x18.wrap`   |
    | `ud60x18`     | Alias for `UD60x18.wrap`  |
    
    ### Conversion Functions
    
    | Name               | Description                                                                 |
    | ------------------ | --------------------------------------------------------------------------- |
    | `convert(SD59x18)` | Converts an SD59x18 number to a simple integer by dividing it by 1e18     |
    | `convert(UD60x18)` | Converts a UD60x18 number to a simple integer by dividing it by 1e18     |
    | `convert(int256)`  | Converts a simple integer to SD59x18 by multiplying it by 1e18           |
    | `convert(uint256)` | Converts a simple integer to UD60x18 type by multiplying it by 1e18       |
  11. Helper Functions for User-Defined Types

    main

    PRBMath provides helper functions (like add, sub, eq, etc.) for user-defined value types. These allow you to perform basic operations without constantly unwrapping and re-wrapping variables. While ergonomic, using these helpers may result in higher gas costs than unwrapping and using vanilla types directly.

    | Name           | Operator | Description               |
    | -------------- | --------- | ------------------------- |
    | `add`          | `+`       | Checked addition          |
    | `and`          | `&`       | Logical AND               |
    | `eq`           | `==`      | Equality                  |
    | `gt`           | `>`       | Greater than operator     |
    | `gte`          | `>=`      | Greater than or equal to  |
    | `isZero`       | N/A       | Check if a number is zero |
    | `lshift`       | N/A       | Bitwise left shift        |
    | `lt`           | `<`       | Less than                 |
    | `lte`          | `<=`      | Less than or equal to      |
    | `mod`          | `%`       | Modulo                    |
    | `neq`          | `!=`      | Not equal operator       |
    | `not`          | `~`       | Negation operator        |
    | `or`           | `|`       | Logical OR                |
    | `rshift`       | N/A       | Bitwise right shift       |
    | `sub`          | `-`       | Checked subtraction       |
    | `unary`        | `-`       | Checked unary             |
    | `uncheckedAdd` | N/A       | Unchecked addition        |
    | `uncheckedSub` | N/A       | Unchecked subtraction     |
    | `xor`          | `^`       | Exclusive or (XOR)        |
  12. Mathematical Functions Reference

    main

    Both SD59x18 and UD60x18 support the following mathematical operations:

    | Name    | Operator | Description                                      |
    | ------- | -------- | ------------------------------------------------ |
    | `abs`   | N/A      | Absolute value                                   |
    | `avg`   | N/A      | Arithmetic average                               |
    | `ceil`  | N/A      | Smallest whole number greater than or equal to x |
    | `div`   | `/`      | Fixed-point division                             |
    | `exp`   | N/A      | Natural exponential e^x                           |
    | `exp2`  | N/A      | Binary exponential 2^x                           |
    | `floor` | N/A      | Greatest whole number less than or equal to x |
    | `frac`  | N/A      | Fractional part                                  |
    | `gm`    | N/A      | Geometric mean                                   |
    | `inv`   | N/A      | Inverse 1÷x                                      |
    | `ln`    | N/A      | Natural logarithm ln(x)                          |
    | `log10` | N/A      | Common logarithm log10(x)                        |
    | `log2`  | N/A      | Binary logarithm log2(x)                         |
    | `mul`   | `*`      | Fixed-point multiplication                       |
    | `pow`   | N/A      | Power function x^y                               |
    | `powu`  | N/A      | Power function x^y with y simple integer         |
    | `sqrt`  | N/A      | Square root                                      |