Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/baitcode/cairo-fixed-point-arithmetic

Fixed Point Arithmetic type for Cairo smart contracts
https://github.com/baitcode/cairo-fixed-point-arithmetic

cairo fixed-point fixed-point-arithmetic smart-contracts starknet

Last synced: 1 day ago
JSON representation

Fixed Point Arithmetic type for Cairo smart contracts

Awesome Lists containing this project

README

        


Cairo Fixed Point Arithmetic


Uses 123 bit for integer part and 128 for fractional and packs everything in one felt252





Report a Bug
-
Request a Feature
-
Ask a Question


## About

This crate was born in an effort to create fixed point datatype for [Ekubo Protocol](https://ekubo.org/) governance. It's specifically taiored to be used in smart-contracts. This library features:

- Fixed Point datatype that supports operations: multiplication, division, addition and substraction.
- Data packing and unpacking for smart contract storage.
- Overflow and underflow checking for all operations.
- Additional convenince methods for better performance without conversions such as `u64 by u128 division` method.
- Conversion from `u64`, `u128` and `u256` types.
- Rounding implementation.

Main type this crate export is:

```cairo
#[derive(Debug, Drop, Copy, Serde)]
pub struct UFixedPoint123x128 {
value: u256
}
```

Despite the fact this library don't derive `starknet::Store` it provides `fp::UFixedPoint123x128StorePacking` implementation for use in contract storage.

## Usage

All use-cases are perfectly described by this snippet.

```cairo
// Basic type import
use fp::{ UFixedPoint123x128 };

// Store packing implementation import
use fp::{ UFixedPoint123x128StorePacking };

// Convenience functions to avoid type conversions
use fp::{
div_u64_by_u128,
div_u64_by_fixed_point,
mul_fixed_point_by_u128
}

fn main() {
// Create a fixed point value 1.0
let one: UFixedPoint123x128 = 1_u64.into();
// Create a fixed point value 100.0
let hundred: UFixedPoint123x128 = 100_u64.into();
// Calculate a fixed point value 0.01
let one_over_hundred = one / hundred;
// OR
let other_example = div_u64_by_u128(1, 100);

assert_eq!(one_over_hundred, other_example );

let multiplication_is_supported = one_over_hundred * hundred;
assert_eq!(multiplication_is_supported, 1_u64.into());

let two: UFixedPoint123x128 = 2_u64.into();
let three: UFixedPoint123x128 = 3_u64.into();
let six: UFixedPoint123x128 = 6_u64.into();
let one_over_three = one / three;
let one_over_six = one / six;

// PartialEq is implemented, values are equal if they are close enough.
// Difference is less than 1 / 2^124
assert_eq!(one_over_three, one_over_six * two);
}
```

This crate also provides additional method for `UFixedPoint123x128` type through public
`UFixedPoint123x128Impl` which implements `UFixedPointTrait`.

```cairo
// Additional methods implementation
use fp::{ UFixedPoint123x128Impl };

UFixedPoint123x128Impl implements UFixedPointTrait

trait UFixedPointTrait {
// Returns integer part of the fixed point value
fn get_integer(self: UFixedPoint123x128) -> u128;

// Returns fractional part of the fixed point value
fn get_fractional(self: UFixedPoint123x128) -> u128;

// Rounds fixed point and returns integer part. 0.5 is rounded up.
fn round(self: UFixedPoint123x128) -> u128;
}
```

## Contributing

[WIP] but feel free to open issue, discuss it with me and submit PR upon assignment.

## Special Thanks


Shramee Srivastav


Shramee Srivastav



For submitting bug report on unchecked error during packing due to incorrect MAX_INT value.

## PS

Love and peace, dude. Hope it was useful.