From bd9627771af1dacd1346c517916272a8f94ed8ff Mon Sep 17 00:00:00 2001 From: mootz12 Date: Wed, 6 Dec 2023 16:40:47 -0500 Subject: [PATCH] chore: add readme and gh actions for release --- .github/workflows/cargo_publish.yml | 16 ++++++++++ .github/workflows/pull_request.yml | 34 +++++++++++++++++++++ README.md | 46 +++++++++++++++++++++-------- 3 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/cargo_publish.yml create mode 100644 .github/workflows/pull_request.yml diff --git a/.github/workflows/cargo_publish.yml b/.github/workflows/cargo_publish.yml new file mode 100644 index 0000000..cedbc37 --- /dev/null +++ b/.github/workflows/cargo_publish.yml @@ -0,0 +1,16 @@ +name: Cargo Publish + +on: + release: + types: [published] + +jobs: + + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - run: cargo publish -p soroban-fixed-point-math + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 0000000..a62c01e --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,34 @@ +name: pull_request + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + + complete: + if: always() + needs: [fmt, build-and-test] + runs-on: ubuntu-latest + steps: + - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: exit 1 + + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - run: cargo fmt --all --check + + build-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - run: cargo build + - run: cargo test \ No newline at end of file diff --git a/README.md b/README.md index 50ead84..7df3fcc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# fixed-point-math -A light fixed-point math library for Rust. Written specifically to be used in [Soroban](https://soroban.stellar.org/) and other WASM based blockchain environments. +# soroban-fixed-point-math +A fixed-point math library for Soroban smart contacts. ## Safety This is **experimental software** and is provided on an "as is" and "as available" basis. @@ -11,28 +11,48 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -fixed-point-math = "" +soroban_fixed_point_math = "" ``` +### FixedPoint Trait + +The `FixedPoint` trait is implemented for the Rust generic integers `i64`, `u64`, `i128`, and `u128`. Any overflow or divide by zero that occurs during the fixed point math calculation will return a value of `None`, in line with Rust's existing checked math functions. + +Phantom overflows are errors that result from an overflow during an intermediate calculation, but the expected result would be within bounds. This trait manages this differently for each implemented integer type: + +* i64 and u64 + * In the event of a phantom overflow, the intermediary computation gets scaled to `i128` / `u128` and is retried. +* i128 and u128 + * In the event of a phantom overflow, the function will terminate and return `None`. If you need larger numbers to be handled, please use the `SorobanFixedPoint` trait. + +### SorobanFixedPoint Trait + +The `SorobanFixedPoint` trait is implemented for the Soroban host types `I256` and `U256`. The trait will panic if any `I256` or `U256` arithmetic error occurs, as host function calls panic by default. + +Additional implementations of the `SorobanFixedPoint` trait are included for `i128` and `u128` integer types to support larger intermediary computations. This removes the majority of phantom overflow events for 128 bit fixed point math. + ### Examples -Fixed-point math support is currently added to both `i128` and `u64` types. For any supported number, you can perform fixed-point operations like this: +For any supported type implementing `FixedPoint`, you can perform fixed-point operations like this: ```rust -use fixed_point_math::{STROOP, FixedPoint}; +use soroban_fixed_point_math::FixedPoint; let x: u64 = 1_5000000; let y: u64 = 2_0000000; -assert_eq!(x.fixed_mul_floor(y, STROOP).unwrap(), 3_0000000); +assert_eq!(x.fixed_mul_floor(y, 1_0000000).unwrap(), 3_0000000); ``` -## Overflow -Overflowing results are handled in the same manner as Rust's built-in "checked" math, by returning `None`. +For any support type implementing `SorobanFixedPoint`, you can perform fixed-point operations like this: -Fixed-point math also deals with phantom overflows, where an intermediary computation overflows but the expected result would be within bounds. This library manages this differently for each supported type: -* i128 - * No extra handling is done. `i128` is large enough to support most computation with 7/9 decimal values. However, its likely 18-decimal math will encounter overflows. -* u64 - * The intermediary computation gets scaled to `u128`, and it is attempted again. +```rust +use soroban_fixed_point_math::SorobanFixedPoint; +use soroban_sdk::{Env, I256}; + +let env: Env //... from your contract, or Env::default() in a test +let x: I256 = I256::from_i32(&env, 1_5000000); +let y: I256 = I256::from_i32(&env, 2_0000000); +assert_eq!(x.fixed_mul_ceil(x, y, I256::from_i32(&env, 1_0000000)), 3_0000000); +``` ## Acknowledgements This library was inspired by or directly modified from many sources, primary: